Initial Contribution
Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
new file mode 100644
index 0000000..72d7b18
--- /dev/null
+++ b/tests/e2e-client/pom.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-client</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-client</name>
+
+ <description>Jersey E2E Client tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-freemarker</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-mustache</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson1</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jettison</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jdk-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth2-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/AbortResponseClientTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/AbortResponseClientTest.java
new file mode 100644
index 0000000..d312a3c
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/AbortResponseClientTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests aborting the request on the client side.
+ *
+ * @author Miroslav Fuksa
+ */
+public class AbortResponseClientTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Test
+ public void testRequestAbort() {
+
+ final Date date = getDate();
+
+ ClientRequestFilter outFilter = new ClientRequestFilter() {
+
+ @Override
+ public void filter(ClientRequestContext context) throws IOException {
+ NewCookie cookie1 = new NewCookie("cookie1", "cookie1");
+ NewCookie cookie2 = new NewCookie("cookie2", "cookie2");
+ final Response response = Response.ok().cookie(cookie1).cookie(cookie2)
+ .header("head1", "head1").header(HttpHeaders.DATE, date).header(HttpHeaders.ETAG,
+ "\"123465\"").header(HttpHeaders.CONTENT_LANGUAGE, "language").header(HttpHeaders.LAST_MODIFIED,
+ date).header(HttpHeaders.CONTENT_LENGTH, 99).type(MediaType.TEXT_HTML_TYPE)
+ .location(URI.create("www.oracle.com")).build();
+
+ // abort the request
+ context.abortWith(response);
+ }
+ };
+ ClientResponseFilter inFilter = new ClientResponseFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext,
+ ClientResponseContext responseContext) throws IOException {
+ Map<String, NewCookie> map = responseContext.getCookies();
+ assertEquals("cookie1", map.get("cookie1").getValue());
+ assertEquals("cookie2", map.get("cookie2").getValue());
+ final MultivaluedMap<String, String> headers = responseContext.getHeaders();
+ assertEquals("head1", headers.get("head1").get(0));
+ assertEquals(date.getTime(), responseContext.getDate().getTime());
+ }
+ };
+
+ WebTarget target = target().path("test");
+ target.register(outFilter).register(inFilter);
+ Invocation i = target.request().buildGet();
+ Response r = i.invoke();
+
+ assertEquals("head1", r.getHeaderString("head1"));
+ assertEquals("cookie1", r.getCookies().get("cookie1").getValue());
+ assertEquals("cookie2", r.getCookies().get("cookie2").getValue());
+ assertEquals(date.getTime(), r.getDate().getTime());
+ assertEquals("123465", r.getEntityTag().getValue());
+ assertEquals("language", r.getLanguage().toString());
+ assertEquals(date.getTime(), r.getLastModified().getTime());
+ // Assert.assertEquals("uri", r.getLink("link")); TODO: not supported yet
+ assertEquals("www.oracle.com", r.getLocation().toString());
+ assertEquals(MediaType.TEXT_HTML_TYPE, r.getMediaType());
+ assertEquals(99, r.getLength());
+
+ assertEquals(200, r.getStatus());
+ }
+
+ private Date getDate() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 2012);
+ cal.set(Calendar.MONTH, 7);
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+ cal.set(Calendar.HOUR, 10);
+ cal.set(Calendar.MINUTE, 5);
+ cal.set(Calendar.SECOND, 1);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @GET
+ public String get() {
+ return "this will never be called.";
+ }
+
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BasicClientTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BasicClientTest.java
new file mode 100644
index 0000000..996adb1
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BasicClientTest.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientAsyncExecutor;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.spi.ThreadPoolExecutorProvider;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import static javax.ws.rs.client.Entity.text;
+
+/**
+ * Tests sync and async client invocations.
+ *
+ * @author Miroslav Fuksa
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class BasicClientTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ // enable(TestProperties.LOG_TRAFFIC);
+ // enable(TestProperties.DUMP_ENTITY);
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testCustomExecutorsAsync() throws ExecutionException, InterruptedException {
+ ClientConfig jerseyConfig = new ClientConfig();
+ jerseyConfig.register(CustomExecutorProvider.class).register(ThreadInterceptor.class);
+ Client client = ClientBuilder.newClient(jerseyConfig);
+ runCustomExecutorTestAsync(client);
+ }
+
+ @Test
+ public void testCustomExecutorsInstanceAsync() throws ExecutionException, InterruptedException {
+ ClientConfig jerseyConfig = new ClientConfig();
+ jerseyConfig.register(new CustomExecutorProvider()).register(ThreadInterceptor.class);
+ Client client = ClientBuilder.newClient(jerseyConfig);
+ runCustomExecutorTestAsync(client);
+ }
+
+ @Test
+ public void testCustomExecutorsSync() throws ExecutionException, InterruptedException {
+ ClientConfig jerseyConfig = new ClientConfig();
+ jerseyConfig.register(CustomExecutorProvider.class).register(ThreadInterceptor.class);
+ Client client = ClientBuilder.newClient(jerseyConfig);
+ runCustomExecutorTestSync(client);
+ }
+
+ @Test
+ public void testCustomExecutorsInstanceSync() throws ExecutionException, InterruptedException {
+ ClientConfig jerseyConfig = new ClientConfig();
+ jerseyConfig.register(new CustomExecutorProvider()).register(ThreadInterceptor.class);
+ Client client = ClientBuilder.newClient(jerseyConfig);
+ runCustomExecutorTestSync(client);
+ }
+
+ private void runCustomExecutorTestAsync(Client client) throws InterruptedException, ExecutionException {
+ AsyncInvoker async = client.target(getBaseUri()).path("resource").request().async();
+
+ Future<Response> f1 = async.post(text("post"));
+ final Response response = f1.get();
+ final String entity = response.readEntity(String.class);
+ assertEquals("custom-async-request-post", entity);
+ }
+
+ private void runCustomExecutorTestSync(Client client) {
+ WebTarget target = client.target(getBaseUri()).path("resource");
+ final Response response = target.request().post(text("post"));
+
+ final String entity = response.readEntity(String.class);
+ assertNotSame("custom-async-request-post", entity);
+ }
+
+ @Test
+ public void testAsyncClientInvocation() throws InterruptedException, ExecutionException {
+ final WebTarget resource = target().path("resource");
+
+ Future<Response> f1 = resource.request().async().post(text("post1"));
+ final Response response = f1.get();
+ assertEquals("post1", response.readEntity(String.class));
+
+ Future<String> f2 = resource.request().async().post(text("post2"), String.class);
+ assertEquals("post2", f2.get());
+
+ Future<List<JaxbString>> f3 = resource.request().async().get(new GenericType<List<JaxbString>>() {
+ });
+ assertEquals(
+ Arrays.asList("a", "b", "c").toString(),
+ f3.get().stream().map(input -> input.value).collect(Collectors.toList()).toString());
+
+ CompletableFuture<String> future1 = new CompletableFuture<>();
+ final TestCallback<Response> c1 = new TestCallback<Response>(future1) {
+
+ @Override
+ protected String process(Response result) {
+ return result.readEntity(String.class);
+ }
+ };
+
+ resource.request().async().post(text("post"), c1);
+ assertEquals("post", future1.get());
+
+ CompletableFuture<String> future2 = new CompletableFuture<>();
+ final TestCallback<String> c2 = new TestCallback<String>(future2) {
+
+ @Override
+ protected String process(String result) {
+ return result;
+ }
+ };
+ resource.request().async().post(text("post"), c2);
+ assertEquals("post", future2.get());
+
+ CompletableFuture<String> future3 = new CompletableFuture<>();
+ final TestCallback<List<JaxbString>> c3 = new TestCallback<List<JaxbString>>(future3) {
+
+ @Override
+ protected String process(List<JaxbString> result) {
+ return result.stream().map(jaxbString -> jaxbString.value).collect(Collectors.toList()).toString();
+ }
+ };
+ resource.request().async().get(c3);
+ assertEquals(Arrays.asList("a", "b", "c").toString(), future3.get());
+ }
+
+ @Test
+ public void testAsyncClientInvocationErrorResponse() throws InterruptedException, ExecutionException {
+ final WebTarget errorResource = target().path("resource").path("error");
+
+ Future<Response> f1 = errorResource.request().async().get();
+ final Response response = f1.get();
+ assertEquals(404, response.getStatus());
+ assertEquals("error", response.readEntity(String.class));
+
+ Future<String> f2 = errorResource.request().async().get(String.class);
+ try {
+ f2.get();
+ fail("ExecutionException expected.");
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ assertTrue(WebApplicationException.class.isAssignableFrom(cause.getClass()));
+ final Response r = ((WebApplicationException) cause).getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+
+ Future<List<String>> f3 = target().path("resource").path("errorlist").request()
+ .async().get(new GenericType<List<String>>() {
+ });
+ try {
+ f3.get();
+ fail("ExecutionException expected.");
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ assertTrue(WebApplicationException.class.isAssignableFrom(cause.getClass()));
+ final Response r = ((WebApplicationException) cause).getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+
+ CompletableFuture<String> future1 = new CompletableFuture<>();
+ final TestCallback<Response> c1 = new TestCallback<Response>(future1) {
+
+ @Override
+ protected String process(Response result) {
+ return result.readEntity(String.class);
+ }
+ };
+ errorResource.request().async().get(c1);
+ assertEquals("error", future1.get());
+
+ CompletableFuture<String> future2 = new CompletableFuture<>();
+ final TestCallback<String> c2 = new TestCallback<String>(future2) {
+
+ @Override
+ protected String process(String result) {
+ return result;
+ }
+ };
+ errorResource.request().async().get(c2);
+ try {
+ future2.get();
+ fail("ExecutionException expected.");
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ assertTrue(WebApplicationException.class.isAssignableFrom(cause.getClass()));
+ final Response r = ((WebApplicationException) cause).getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+
+ CompletableFuture<String> future3 = new CompletableFuture<>();
+ final TestCallback<List<JaxbString>> c3 = new TestCallback<List<JaxbString>>(future3) {
+
+ @Override
+ protected String process(List<JaxbString> result) {
+ return result.stream().map(jaxbString -> jaxbString.value).collect(Collectors.toList()).toString();
+ }
+ };
+ target().path("resource").path("errorlist").request().async().get(c3);
+ try {
+ future3.get();
+ fail("ExecutionException expected.");
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ assertTrue(WebApplicationException.class.isAssignableFrom(cause.getClass()));
+ final Response r = ((WebApplicationException) cause).getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+ }
+
+ @Test
+ public void testSyncClientInvocation() throws InterruptedException, ExecutionException {
+ final WebTarget resource = target().path("resource");
+
+ Response r1 = resource.request().post(text("post1"));
+ assertEquals("post1", r1.readEntity(String.class));
+
+ String r2 = resource.request().post(text("post2"), String.class);
+ assertEquals("post2", r2);
+
+ List<JaxbString> r3 = resource.request().get(new GenericType<List<JaxbString>>() {
+ });
+ assertEquals(Arrays.asList("a", "b", "c").toString(),
+ r3.stream().map(input -> input.value).collect(Collectors.toList()).toString());
+ }
+
+ @Test
+ public void testSyncClientInvocationErrorResponse() throws InterruptedException, ExecutionException {
+ final WebTarget errorResource = target().path("resource").path("error");
+
+ Response r1 = errorResource.request().get();
+ assertEquals(404, r1.getStatus());
+ assertEquals("error", r1.readEntity(String.class));
+
+ try {
+ errorResource.request().get(String.class);
+ fail("ExecutionException expected.");
+ } catch (WebApplicationException ex) {
+ final Response r = ex.getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+
+ try {
+ target().path("resource").path("errorlist").request().get(new GenericType<List<String>>() {
+ });
+ fail("ExecutionException expected.");
+ } catch (WebApplicationException ex) {
+ final Response r = ex.getResponse();
+ assertEquals(404, r.getStatus());
+ assertEquals("error", r.readEntity(String.class));
+ }
+ }
+
+ @Test
+ // JERSEY-1412
+ public void testAbortAsyncRequest() throws Exception {
+ Invocation invocation = abortingTarget().request().buildPost(text("entity"));
+ Future<String> future = invocation.submit(String.class);
+ assertEquals("aborted", future.get());
+ }
+
+ @Test
+ // JERSEY-1412
+ public void testAbortSyncRequest() throws Exception {
+ Invocation invocation = abortingTarget().request().buildPost(text("entity"));
+ String response = invocation.invoke(String.class);
+ assertEquals("aborted", response);
+ }
+
+ protected WebTarget abortingTarget() {
+ Client client = ClientBuilder.newClient();
+ client.register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext ctx) throws IOException {
+ Response r = Response.ok("aborted").build();
+ ctx.abortWith(r);
+ }
+ });
+ return client.target("http://any.web:888");
+ }
+
+ @ClientAsyncExecutor
+ public static class CustomExecutorProvider extends ThreadPoolExecutorProvider {
+
+ /**
+ * Create a new instance of the thread pool executor provider.
+ */
+ public CustomExecutorProvider() {
+ super("custom-async-request");
+ }
+ }
+
+ public static class ThreadInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final String name = Thread.currentThread().getName(); // e.g. custom-async-request-0
+ final int lastIndexOfDash = name.lastIndexOf('-');
+ context.setEntity(
+ name.substring(0, lastIndexOfDash < 0 ? name.length() : lastIndexOfDash) + "-" + context.getEntity());
+ context.proceed();
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ @Path("error")
+ public String getError() {
+ throw new NotFoundException(Response.status(404).type("text/plain").entity("error").build());
+ }
+
+ @GET
+ @Path("errorlist")
+ @Produces(MediaType.APPLICATION_XML)
+ public List<JaxbString> getErrorList() {
+ throw new NotFoundException(Response.status(404).type("text/plain").entity("error").build());
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_XML)
+ public List<JaxbString> get() {
+ return Arrays.asList(new JaxbString("a"), new JaxbString("b"), new JaxbString("c"));
+ }
+
+ @POST
+ public String post(String entity) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return entity;
+ }
+ }
+
+ private abstract static class TestCallback<T> implements InvocationCallback<T> {
+
+ private final CompletableFuture<String> completableFuture;
+
+ TestCallback(CompletableFuture<String> completableFuture) {
+ this.completableFuture = completableFuture;
+ }
+
+ @Override
+ public void completed(T result) {
+ try {
+ completableFuture.complete(process(result));
+ } catch (Throwable t) {
+ completableFuture.completeExceptionally(t);
+ }
+ }
+
+ protected abstract String process(T result);
+
+ @Override
+ public void failed(Throwable error) {
+ if (error.getCause() instanceof WebApplicationException) {
+ completableFuture.completeExceptionally(error.getCause());
+ } else {
+ completableFuture.completeExceptionally((error));
+ }
+ }
+ }
+
+ @XmlRootElement
+ public static class JaxbString {
+
+ public String value;
+
+ public JaxbString() {
+ }
+
+ public JaxbString(String value) {
+ this.value = value;
+ }
+ }
+}
+
+
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BufferingTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BufferingTest.java
new file mode 100644
index 0000000..a691fc8
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/BufferingTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests chunk encoding and possibility of buffering the entity.
+ *
+ * @author Miroslav Fuksa
+ */
+public class BufferingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class, LoggingFeature.class);
+ }
+
+ @Path("resource")
+ public static class MyResource {
+ @POST
+ public String getBuffered(@HeaderParam("content-length") String contentLenght,
+ @HeaderParam("transfer-encoding") String transferEncoding) {
+ if (transferEncoding != null && transferEncoding.equals("chunked")) {
+ return "chunked";
+ }
+ return contentLenght;
+ }
+ }
+
+ @Test
+ public void testApacheConnector() {
+ testWithBuffering(getApacheConnectorConfig());
+ testWithChunkEncodingWithoutPropertyDefinition(getApacheConnectorConfig());
+ testWithChunkEncodingWithPropertyDefinition(getApacheConnectorConfig());
+ testWithChunkEncodingPerRequest(getApacheConnectorConfig());
+ testDefaultOption(getApacheConnectorConfig(), RequestEntityProcessing.CHUNKED);
+ }
+
+ @Test
+ public void testGrizzlyConnector() {
+ testWithBuffering(getGrizzlyConnectorConfig());
+ testWithChunkEncodingWithoutPropertyDefinition(getGrizzlyConnectorConfig());
+ testWithChunkEncodingWithPropertyDefinition(getGrizzlyConnectorConfig());
+ testWithChunkEncodingPerRequest(getGrizzlyConnectorConfig());
+ testDefaultOption(getGrizzlyConnectorConfig(), RequestEntityProcessing.CHUNKED);
+ }
+
+ @Test
+ public void testHttpUrlConnector() {
+ testWithBuffering(getHttpUrlConnectorConfig());
+ testWithChunkEncodingWithoutPropertyDefinition(getHttpUrlConnectorConfig());
+ testWithChunkEncodingWithPropertyDefinition(getHttpUrlConnectorConfig());
+ testWithChunkEncodingPerRequest(getHttpUrlConnectorConfig());
+ testDefaultOption(getHttpUrlConnectorConfig(), RequestEntityProcessing.BUFFERED);
+ }
+
+ private ClientConfig getApacheConnectorConfig() {
+ return new ClientConfig().connectorProvider(new ApacheConnectorProvider());
+ }
+
+ private ClientConfig getGrizzlyConnectorConfig() {
+ return new ClientConfig().connectorProvider(new GrizzlyConnectorProvider());
+ }
+
+ private ClientConfig getHttpUrlConnectorConfig() {
+ return new ClientConfig();
+ }
+
+ private void testDefaultOption(ClientConfig cc, RequestEntityProcessing mode) {
+ String entity = getVeryLongString();
+ makeRequest(cc, entity, mode == RequestEntityProcessing.BUFFERED ? String.valueOf(entity.length())
+ : "chunked");
+ }
+
+ private void testWithBuffering(ClientConfig cc) {
+ cc.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
+ String entity = getVeryLongString();
+
+ makeRequest(cc, entity, String.valueOf(entity.length()));
+ }
+
+ private void makeRequest(ClientConfig cc, String entity, String expected) {
+ Client client = ClientBuilder.newClient(cc);
+ WebTarget target = client.target(UriBuilder.fromUri(getBaseUri()).path("resource").build());
+
+ Response response = target.request().post(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(expected, response.readEntity(String.class));
+ }
+
+ private void testWithChunkEncodingWithPropertyDefinition(ClientConfig cc) {
+ cc.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+ cc.property(ClientProperties.CHUNKED_ENCODING_SIZE, 3000);
+ String entity = getVeryLongString();
+
+ makeRequest(cc, entity, "chunked");
+ }
+
+ private void testWithChunkEncodingWithoutPropertyDefinition(ClientConfig cc) {
+ cc.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+ String entity = getVeryLongString();
+
+ makeRequest(cc, entity, "chunked");
+ }
+
+
+ /**
+ * Tests that {@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING} can be defined
+ * per request with different values.
+ */
+ private void testWithChunkEncodingPerRequest(ClientConfig cc) {
+ cc.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+
+ cc.property(ClientProperties.CHUNKED_ENCODING_SIZE, 3000);
+ Client client = ClientBuilder.newClient(cc);
+ WebTarget target = client.target(UriBuilder.fromUri(getBaseUri()).path("resource").build());
+
+ String entity = getVeryLongString();
+ Response response = target.request().post(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("chunked", response.readEntity(String.class));
+
+ response = target.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
+ .request().post(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(String.valueOf(entity.length()), response.readEntity(String.class));
+ }
+
+ public String getVeryLongString() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 1; i++) {
+ sb.append("helllllloooooooooooooooooooooooooooooouuuuuuuuuuu.");
+ }
+ return sb.toString();
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/CancelFutureClientTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/CancelFutureClientTest.java
new file mode 100644
index 0000000..af0ade7
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/CancelFutureClientTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests the behaviour of the Async client when the {@link java.util.concurrent.Future} is cancelled.
+ *
+ * <p>
+ * Tests, that if the async request future is cancelled by the client,
+ * the {@link javax.ws.rs.client.InvocationCallback#completed(Object)} callback is not invoked and that
+ * {@link java.util.concurrent.CancellationException} is correctly returned (according to spec.) to
+ * {@link javax.ws.rs.client.InvocationCallback#failed(Throwable)} callback method.
+ * </p>
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class CancelFutureClientTest extends JerseyTest {
+
+ public static final long MAX_WAITING_SECONDS = 2L;
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Test
+ public void testCancelFuture() throws InterruptedException, TimeoutException {
+ Future<Response> future = target().path("test").request().async().get(
+ new InvocationCallback<Response>() {
+ public void completed(final Response response) {
+ fail("[completed()] callback was invoked, although the Future should have been cancelled.");
+ }
+
+ public void failed(final Throwable throwable) {
+ assertEquals(CancellationException.class, throwable.getClass());
+ countDownLatch.countDown();
+ }
+ }
+ );
+ if (!future.cancel(true)) {
+ fail("The Future could not be canceled.");
+ }
+
+ // prevent the test container to stop the method execution before the callbacks can be reached.
+ if (!countDownLatch.await(MAX_WAITING_SECONDS * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS)) {
+ throw new TimeoutException("Callback was not triggered within the time limit." + countDownLatch.getCount());
+ }
+ }
+
+ @Path("test")
+ public static class TestResource {
+ @GET
+ public Response get() {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return Response.noContent().build();
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ChunkedInputStreamClosedPrematurelyTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ChunkedInputStreamClosedPrematurelyTest.java
new file mode 100644
index 0000000..11f5c31
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ChunkedInputStreamClosedPrematurelyTest.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+/**
+ * Reproducer for JERSEY-2705. Client side entity InputStream exception
+ * in chunked mode should not lead to the same behavior on the server side,
+ * as if no exception occurred at all.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ChunkedInputStreamClosedPrematurelyTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(ChunkedInputStreamClosedPrematurelyTest.class.getName());
+ private static final Exception NO_EXCEPTION = new Exception("No exception.");
+
+ private static final AtomicInteger NEXT_REQ_ID = new AtomicInteger(0);
+ private static final String REQ_ID_PARAM_NAME = "test-req-id";
+ private static final int BYTES_TO_SEND = 1024 * 1024 + 13;
+
+ @Path("/test")
+ @SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "JavaDoc"})
+ public static class TestResource {
+
+ private static final ConcurrentMap<String, SettableFuture<Exception>> REQUEST_MAP = new ConcurrentHashMap<>();
+
+ @QueryParam(REQ_ID_PARAM_NAME)
+ private String reqId;
+
+ @POST
+ public String post(InputStream is) {
+ final byte[] buffer = new byte[4096];
+ int readTotal = 0;
+
+ Exception thrown = NO_EXCEPTION;
+ try {
+ int read;
+ while ((read = is.read(buffer)) > -1) {
+ readTotal += read;
+ }
+ } catch (Exception ex) {
+ thrown = ex;
+ }
+
+ if (!getFutureFor(reqId).set(thrown)) {
+ LOGGER.log(Level.WARNING,
+ "Unable to set stream processing exception into the settable future instance for request id " + reqId,
+ thrown);
+ }
+
+ return Integer.toString(readTotal);
+ }
+
+ @Path("/requestWasMade")
+ @GET
+ public Boolean getRequestWasMade() {
+ // add a new future for the request if not there yet to avoid race conditions with POST processing
+ final SettableFuture<Exception> esf = getFutureFor(reqId);
+ try {
+ // wait for up to three second for a request to be made;
+ // there is always a value, if set...
+ return esf.get(3, TimeUnit.SECONDS) != null;
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ throw new InternalServerErrorException("Post request processing has timed out for request id " + reqId, e);
+ }
+ }
+
+ @Path("/requestCausedException")
+ @GET
+ public Boolean getRequestCausedException() {
+ final SettableFuture<Exception> esf = getFutureFor(reqId);
+ try {
+ return esf.get(3, TimeUnit.SECONDS) != NO_EXCEPTION;
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ throw new InternalServerErrorException("Post request processing has timed out for request id " + reqId, e);
+ }
+ }
+
+ private SettableFuture<Exception> getFutureFor(String key) {
+ final SettableFuture<Exception> esf = SettableFuture.create();
+ final SettableFuture<Exception> oldEsf = REQUEST_MAP.putIfAbsent(key, esf);
+ return (oldEsf != null) ? oldEsf : esf;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+ config.property(ClientProperties.CHUNKED_ENCODING_SIZE, 7);
+ }
+
+ /**
+ * A sanity test to check the normal use case is working as expected.
+ */
+ @Test
+ public void testUninterrupted() {
+ final String testReqId = nextRequestId("testUninterrupted");
+
+ Response testResponse = target("test").queryParam(REQ_ID_PARAM_NAME, testReqId)
+ .request().post(Entity.entity("0123456789ABCDEF", MediaType.APPLICATION_OCTET_STREAM));
+ assertEquals("Unexpected response status code.", 200, testResponse.getStatus());
+ assertEquals("Unexpected response entity.", "16", testResponse.readEntity(String.class));
+
+ assertTrue("POST request " + testReqId + " has not reached the server.",
+ target("test").path("requestWasMade").queryParam(REQ_ID_PARAM_NAME, testReqId)
+ .request().get(Boolean.class));
+ assertFalse("POST request " + testReqId + " has caused an unexpected exception on the server.",
+ target("test").path("requestCausedException").queryParam(REQ_ID_PARAM_NAME, testReqId)
+ .request().get(Boolean.class));
+ }
+
+ /**
+ * This test simulates how Jersey Client should behave after JERSEY-2705 gets fixed.
+ *
+ * @throws Exception in case the test fails to execute.
+ */
+ @Test
+ public void testInterruptedJerseyHttpUrlConnection() throws Exception {
+
+ final String testReqId = nextRequestId("testInterruptedJerseyHttpUrlConnection");
+
+ URL postUrl = UriBuilder.fromUri(getBaseUri()).path("test").queryParam(REQ_ID_PARAM_NAME, testReqId).build().toURL();
+ final HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();
+
+ try {
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", MediaType.APPLICATION_OCTET_STREAM);
+ connection.setDoOutput(true);
+ connection.setChunkedStreamingMode(1024);
+ OutputStream entityStream = connection.getOutputStream();
+ ReaderWriter.writeTo(new ExceptionThrowingInputStream(BYTES_TO_SEND), entityStream);
+ Assert.fail("Expected ProcessingException has not been thrown.");
+ } catch (IOException expected) {
+ // so far so good
+ } finally {
+ connection.disconnect();
+ }
+ // we should make it to the server, but there the exceptional behaviour should get noticed
+ assertTrue("POST request " + testReqId + " has not reached the server.",
+ target("test").path("requestWasMade").queryParam(REQ_ID_PARAM_NAME, testReqId).request().get(Boolean.class));
+ assertTrue("POST request " + testReqId + " did not cause an expected exception on the server.",
+ target("test").path("requestCausedException").queryParam(REQ_ID_PARAM_NAME, testReqId)
+ .request().get(Boolean.class));
+ }
+
+ /**
+ * This test reproduces the Jersey Client behavior reported in JERSEY-2705.
+ */
+ @Ignore
+ @Test
+ public void testInterruptedJerseyClient() {
+ final String testReqId = nextRequestId("testInterruptedJerseyClient");
+
+ try {
+ target("test").queryParam(REQ_ID_PARAM_NAME, testReqId).request()
+ .post(Entity.entity(new ExceptionThrowingInputStream(BYTES_TO_SEND), MediaType.APPLICATION_OCTET_STREAM));
+ Assert.fail("Expected ProcessingException has not been thrown.");
+ } catch (ProcessingException expected) {
+ // so far so good
+ }
+ // we should make it to the server, but there the exceptional behaviour should get noticed
+ assertTrue("POST request " + testReqId + " has not reached the server.",
+ target("test").path("requestWasMade").queryParam(REQ_ID_PARAM_NAME, testReqId).request().get(Boolean.class));
+ assertTrue("POST request " + testReqId + " did not cause an expected exception on the server.",
+ target("test").path("requestCausedException").queryParam(REQ_ID_PARAM_NAME, testReqId)
+ .request().get(Boolean.class));
+ }
+
+ private static String nextRequestId(String testMethodName) {
+ return String.format(testMethodName + "-%03d", NEXT_REQ_ID.getAndIncrement());
+ }
+
+ /**
+ * InputStream implementation that allows "reading" as many bytes as specified by threshold constructor parameter.
+ * Throws an IOException if read operation is attempted after the threshold is exceeded.
+ */
+ private class ExceptionThrowingInputStream extends InputStream {
+
+ private final int threshold;
+ private int offset = 0;
+
+ /**
+ * Get me a new stream that throws exception.
+ *
+ * @param threshold this number of bytes will be read all right
+ */
+ public ExceptionThrowingInputStream(int threshold) {
+ this.threshold = threshold;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (offset++ < threshold) {
+ return 'A';
+ } else {
+ throw new IOException("stream closed");
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ offset += len;
+ if (offset < threshold) {
+ Arrays.fill(b, off, off + len, (byte) 'A');
+ return len;
+ } else {
+ throw new IOException("Stream closed");
+ }
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientBufferingDisabledTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientBufferingDisabledTest.java
new file mode 100644
index 0000000..4a21864
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientBufferingDisabledTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests possibility of disabling buffering of outgoing entity in
+ * {@link org.glassfish.jersey.client.HttpUrlConnectorProvider}.
+ *
+ * @author Miroslav Fuksa
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(ConcurrentRunner.class)
+public class ClientBufferingDisabledTest extends JerseyTest {
+
+ private static final long LENGTH = 200000000L;
+ private static final int CHUNK = 2048;
+ private static CountDownLatch postLatch = new CountDownLatch(1);
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class);
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @POST
+ public long post(InputStream is) throws IOException {
+ int b;
+ long count = 0;
+ boolean firstByte = true;
+ while ((b = is.read()) != -1) {
+ if (firstByte) {
+ firstByte = false;
+ postLatch.countDown();
+ }
+
+ count++;
+ }
+ return count;
+ }
+ }
+
+
+ /**
+ * Test that buffering can be disabled with {@link HttpURLConnection}. By default, the
+ * {@code HttpURLConnection} buffers the output entity in order to calculate the
+ * Content-length request attribute. This cause problems for large entities.
+ * <p>
+ * This test uses {@link HttpUrlConnectorProvider#USE_FIXED_LENGTH_STREAMING} to enable
+ * fix length streaming on {@code HttpURLConnection}.
+ */
+ @Test
+ public void testDisableBufferingWithFixedLengthViaProperty() {
+ postLatch = new CountDownLatch(1);
+
+ // This IS sends out 10 chunks and waits whether they were received on the server. This tests
+ // whether the buffering is disabled.
+ InputStream is = getInputStream();
+
+ final HttpUrlConnectorProvider connectorProvider = new HttpUrlConnectorProvider();
+ ClientConfig clientConfig = new ClientConfig().connectorProvider(connectorProvider);
+ clientConfig.property(HttpUrlConnectorProvider.USE_FIXED_LENGTH_STREAMING, true);
+ Client client = ClientBuilder.newClient(clientConfig);
+ final Response response
+ = client.target(getBaseUri()).path("resource")
+ .request().header(HttpHeaders.CONTENT_LENGTH, LENGTH).post(
+ Entity.entity(is, MediaType.APPLICATION_OCTET_STREAM));
+ Assert.assertEquals(200, response.getStatus());
+ final long count = response.readEntity(long.class);
+ Assert.assertEquals("Unexpected content length received.", LENGTH, count);
+ }
+
+ /**
+ * Test that buffering can be disabled with {@link HttpURLConnection}. By default, the
+ * {@code HttpURLConnection} buffers the output entity in order to calculate the
+ * Content-length request attribute. This cause problems for large entities.
+ * <p>
+ * This test uses {@link HttpUrlConnectorProvider#useFixedLengthStreaming()} to enable
+ * fix length streaming on {@code HttpURLConnection}.
+ */
+ @Test
+ public void testDisableBufferingWithFixedLengthViaMethod() {
+ postLatch = new CountDownLatch(1);
+
+ // This IS sends out 10 chunks and waits whether they were received on the server. This tests
+ // whether the buffering is disabled.
+ InputStream is = getInputStream();
+
+ final HttpUrlConnectorProvider connectorProvider = new HttpUrlConnectorProvider()
+ .useFixedLengthStreaming();
+ ClientConfig clientConfig = new ClientConfig().connectorProvider(connectorProvider);
+ Client client = ClientBuilder.newClient(clientConfig);
+ final Response response
+ = client.target(getBaseUri()).path("resource")
+ .request().header(HttpHeaders.CONTENT_LENGTH, LENGTH).post(
+ Entity.entity(is, MediaType.APPLICATION_OCTET_STREAM));
+ Assert.assertEquals(200, response.getStatus());
+ final long count = response.readEntity(long.class);
+ Assert.assertEquals("Unexpected content length received.", LENGTH, count);
+ }
+
+ /**
+ * Test that buffering can be disabled with {@link HttpURLConnection}. By default, the
+ * {@code HttpURLConnection} buffers the output entity in order to calculate the
+ * Content-length request attribute. This cause problems for large entities.
+ * <p>
+ * In Jersey 1.x chunk encoding with {@code HttpURLConnection} was causing bugs
+ * which occurred from time to time. This looks to be a case also in Jersey 2.x. This test
+ * has failed unpredictably on some machines. Therefore it is disabled now.
+ * </p>
+ */
+ @Test
+ @Ignore("fails unpredictable (see javadoc)")
+ public void testDisableBufferingWithChunkEncoding() {
+ postLatch = new CountDownLatch(1);
+
+ // This IS sends out 10 chunks and waits whether they were received on the server. This tests
+ // whether the buffering is disabled.
+ InputStream is = getInputStream();
+
+ final HttpUrlConnectorProvider connectorProvider = new HttpUrlConnectorProvider()
+ .chunkSize(CHUNK);
+ ClientConfig clientConfig = new ClientConfig()
+ .connectorProvider(connectorProvider);
+ Client client = ClientBuilder.newClient(clientConfig);
+ final Response response
+ = client.target(getBaseUri()).path("resource")
+ .request().post(Entity.entity(is, MediaType.APPLICATION_OCTET_STREAM));
+ Assert.assertEquals(200, response.getStatus());
+ final long count = response.readEntity(long.class);
+ Assert.assertEquals("Unexpected content length received.", LENGTH, count);
+ }
+
+ private InputStream getInputStream() {
+ return new InputStream() {
+ private int cnt = 0;
+
+ @Override
+ public int read() throws IOException {
+ cnt++;
+ if (cnt > CHUNK * 10) {
+ try {
+ postLatch.await(3 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertEquals("waiting for chunk on the server side time-outed", 0, postLatch.getCount());
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ if (cnt <= LENGTH) {
+ return 'a';
+ } else {
+ return -1;
+ }
+ }
+ };
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientDestroyTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientDestroyTest.java
new file mode 100644
index 0000000..9997a12
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientDestroyTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+import javax.annotation.PreDestroy;
+
+import org.glassfish.jersey.client.ClientLifecycleListener;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.JerseyClientBuilder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that pre destroy method on providers is invoked.
+ *
+ * @author Michal Gajdos
+ */
+public class ClientDestroyTest extends JerseyTest {
+
+ private static final Map<String, Boolean> destroyed = new HashMap<>();
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ destroyed.clear();
+ destroyed.put("filter", false);
+ destroyed.put("reader", false);
+ destroyed.put("feature", false);
+
+ super.setUp();
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get(@HeaderParam("foo") final String foo) {
+ return "resource-" + foo;
+ }
+ }
+
+ public static class MyFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().putSingle("foo", "bar");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("filter", true);
+ }
+ }
+
+ public static class MyReader implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final Object entity = context.proceed();
+ return "reader-" + entity;
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("reader", true);
+ }
+ }
+
+ public static class MyFeature implements Feature {
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("feature", true);
+ }
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ return true;
+ }
+ }
+
+ @Test
+ public void testClientInvokePreDestroyMethodOnProviderClass() throws Exception {
+ final Client client = ClientBuilder.newClient()
+ .register(MyFilter.class)
+ .register(MyReader.class)
+ .register(MyFeature.class);
+
+ assertThat(client.target(getBaseUri()).request().get(String.class), is("reader-resource-bar"));
+
+ checkDestroyed(false);
+ client.close();
+ checkDestroyed(true);
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ private void checkDestroyed(final boolean shouldBeDestroyed) {
+ for (final Map.Entry<String, Boolean> entry : destroyed.entrySet()) {
+ assertThat(entry.getKey() + " should" + (shouldBeDestroyed ? "" : " not") + " be destroyed",
+ entry.getValue(), is(shouldBeDestroyed));
+ }
+ }
+
+ public static class FooListener implements ClientRequestFilter, ClientLifecycleListener {
+ public static volatile boolean INITIALIZED = false;
+ public static volatile boolean CLOSED = false;
+
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException { /* do nothing */ }
+
+ @Override
+ public void onClose() {
+ CLOSED = true;
+ }
+
+ @Override
+ public void onInit() {
+ INITIALIZED = true;
+ }
+
+ // to check if closing works also for class-registered providers
+ public static boolean isClosed() {
+ return CLOSED;
+ }
+
+ public static boolean isInitialized() {
+ return INITIALIZED;
+ }
+ }
+
+ public static class BarListener implements ClientRequestFilter, ClientLifecycleListener {
+ protected volatile boolean closed = false;
+ protected volatile boolean initialized = false;
+
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException { /* do nothing */ }
+
+ @Override
+ public void onInit() {
+ this.initialized = true;
+ }
+
+ @Override
+ public synchronized void onClose() {
+ this.closed = true;
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+ }
+
+ // another type needed, as multiple registrations of the same type are not allowed
+ public static class BarListener2 extends BarListener {
+ }
+
+ @Test
+ public void testLifecycleListenerProvider() {
+ final JerseyClientBuilder builder = new JerseyClientBuilder();
+ final JerseyClient client = builder.build();
+
+ final BarListener filter = new BarListener();
+ final BarListener filter2 = new BarListener2();
+
+ // ClientRuntime initializes lazily, so it is forced by invoking a (dummy) request
+ client.register(filter2); // instance registered into client
+ client.target(getBaseUri()).register(filter).request().get(String.class); // instance registration into target
+
+ assertTrue("Filter was expected to be already initialized.", filter.isInitialized());
+ assertTrue("Filter2 was expected to be already initialized.", filter2.isInitialized());
+
+ client.target(getBaseUri()).register(FooListener.class).request().get(String.class); // class registration into target
+
+ assertTrue("Class-registered filter was expected to be already initialized", FooListener.isInitialized());
+
+ assertFalse("Class-registered filter was expected to be still open.", FooListener.isClosed());
+ assertFalse("Filter was expected to be still open.", filter.isClosed());
+ assertFalse("Filter2 was expected to be still open.", filter2.isClosed());
+
+ client.close();
+
+ assertTrue("Class-registered filter was expected to be closed.", FooListener.isClosed());
+ assertTrue("Filter was expected to be closed.", filter.isClosed());
+ assertTrue("Filter2 was expected to be closed.", filter2.isClosed());
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientEntityAnnotationTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientEntityAnnotationTest.java
new file mode 100644
index 0000000..79288c7
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientEntityAnnotationTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests annotations of entity on the client side.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class ClientEntityAnnotationTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(ClientFilter.class);
+ }
+
+ @Test
+ public void test() {
+ Annotation[] annotations = MyProvider.class.getAnnotations();
+ Entity<String> post = Entity.entity("test", MediaType.WILDCARD_TYPE,
+ annotations);
+ final Response response = target().path("resource").request().post(post);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("test", response.readEntity(String.class));
+ }
+
+
+ public static class ClientFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ final Annotation[] entityAnnotations = requestContext.getEntityAnnotations();
+ Assert.assertEquals(1, entityAnnotations.length);
+ Assert.assertEquals(MyProvider.class.getAnnotation(Provider.class), entityAnnotations[0]);
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+ @POST
+ public String post(String entity) {
+ return entity;
+ }
+ }
+
+ @Provider
+ public static class MyProvider {
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorCloseTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorCloseTest.java
new file mode 100644
index 0000000..76c2d3f
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorCloseTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.sse.SseEventSource;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Petr Janouch (petr.janouch at oracle.com)
+ */
+public class ClientExecutorCloseTest extends JerseyTest {
+ private static CountDownLatch cdl = new CountDownLatch(2);
+ private static boolean schedulerFound = false;
+
+ /**
+ * Tests that closing a client shuts down a corresponding client async executor service.
+ */
+ @Test
+ @Ignore("Jersey uses ForkJoin common pool by default, which shouldn't be closed when client closes.")
+ public void testCloseAsyncExecutor() throws InterruptedException {
+ assertFalse(clientExecutorThreadPresent());
+ target("resource").request().async().get();
+ final SseEventSource eventSource = SseEventSource
+ .target(target("resource/fail"))
+ .reconnectingEvery(11, TimeUnit.MILLISECONDS)
+ .build();
+ eventSource.register(System.out::println);
+ eventSource.open();
+ assertTrue("Waiting for eventSource to open time-outed", cdl.await(5000, TimeUnit.MILLISECONDS));
+ assertTrue("Client async executor thread not found.", clientExecutorThreadPresent());
+ assertTrue("Scheduler thread not found.", schedulerFound);
+ client().close();
+ assertFalse("Client async executor thread should have been already removed.",
+ clientExecutorThreadPresent());
+ assertFalse("Client background scheduler thread should have been already removed.",
+ clientSchedulerThreadPresent());
+ }
+
+ private boolean clientExecutorThreadPresent() {
+ Set<Thread> threads = Thread.getAllStackTraces().keySet();
+ return threads.stream().map(Thread::getName).anyMatch(name -> name.contains("jersey-client-async-executor"));
+ }
+
+ private static boolean clientSchedulerThreadPresent() {
+ Set<Thread> threads = Thread.getAllStackTraces().keySet();
+ for (Thread thread : threads) {
+ if (thread.getName().contains("jersey-client-background-scheduler")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ public String getHello() {
+ return "Hello";
+ }
+
+ @GET
+ @Path("fail")
+ public Response fail() {
+ // should return false on first (regular) connect and true on reconnect
+ schedulerFound = clientSchedulerThreadPresent();
+ cdl.countDown();
+ // simulate unsuccessful connect attempt -> force reconnect (eventSource will submit a task into scheduler)
+ return Response.status(503).build();
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorTest.java
new file mode 100644
index 0000000..617b2a0
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientExecutorTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.MessageBodyReader;
+
+import org.glassfish.jersey.client.ClientAsyncExecutor;
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.spi.ExecutorServiceProvider;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ClientExecutorTest extends JerseyTest {
+
+ @Path("ClientExecutorTest")
+ public static class ClientExecutorTestResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "get";
+ }
+ }
+
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ClientExecutorTestResource.class);
+ }
+
+ private volatile String threadName = null;
+
+ @Test
+ public void testCustomExecutorRx() throws InterruptedException {
+
+ ExecutorService clientExecutor =
+ Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("ClientExecutor-%d").build());
+
+ Client client = ClientBuilder.newBuilder().executorService(clientExecutor).build();
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ testRx(client, latch);
+
+ latch.await(3, TimeUnit.SECONDS);
+
+ assertNotNull(threadName);
+ assertThat(threadName, containsString("ClientExecutor"));
+ }
+
+ @Test
+ public void testDefaultExecutorRx() throws InterruptedException {
+
+ Client client = ClientBuilder.newClient();
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ testRx(client, latch);
+
+ latch.await(3, TimeUnit.SECONDS);
+ assertNotNull(threadName);
+ assertThat(threadName, containsString("jersey-client-async-executor"));
+ }
+
+ @Test
+ public void testDefaultExecutorAsync() throws InterruptedException {
+
+ Client client = ClientBuilder.newClient();
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ testAsync(client, latch);
+
+ latch.await(3, TimeUnit.SECONDS);
+ assertNotNull(threadName);
+ assertThat(threadName, containsString("jersey-client-async-executor"));
+ }
+
+ @Test
+ public void testJerseyCustomExecutorAsync() throws InterruptedException {
+ Client client = ClientBuilder.newClient();
+ client.register(MyExecutorProvider.class);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ testAsync(client, latch);
+
+ latch.await(3, TimeUnit.SECONDS);
+ assertNotNull(threadName);
+ assertThat(threadName, containsString("MyExecutorProvider"));
+ }
+
+
+ private void testRx(Client client, CountDownLatch latch) {
+ client.target(UriBuilder.fromUri(getBaseUri()).path("ClientExecutorTest"))
+ .register(new MessageBodyReader<ClientExecutorTest>() {
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public ClientExecutorTest readFrom(Class<ClientExecutorTest> type, Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ ClientExecutorTest.this.threadName = Thread.currentThread().getName();
+ latch.countDown();
+
+ return new ClientExecutorTest();
+
+ }
+ })
+ .request()
+ .rx()
+ .get(ClientExecutorTest.class);
+ }
+
+ private void testAsync(Client client, CountDownLatch latch) {
+ client.target(UriBuilder.fromUri(getBaseUri()).path("ClientExecutorTest"))
+ .register(new MessageBodyReader<ClientExecutorTest>() {
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public ClientExecutorTest readFrom(Class<ClientExecutorTest> type, Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ ClientExecutorTest.this.threadName = Thread.currentThread().getName();
+ latch.countDown();
+
+ return new ClientExecutorTest();
+
+ }
+ })
+ .request()
+ .async()
+ .get(ClientExecutorTest.class);
+ }
+
+ @ClientAsyncExecutor
+ public static class MyExecutorProvider implements ExecutorServiceProvider {
+
+ public final ExecutorService executorService =
+ Executors
+ .newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("MyExecutorProvider-%d").build());
+
+ @Override
+ public ExecutorService getExecutorService() {
+ return executorService;
+ }
+
+ @Override
+ public void dispose(ExecutorService executorService) {
+ executorService.shutdown();
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientFilterTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientFilterTest.java
new file mode 100644
index 0000000..af4290b
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientFilterTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.ResponseProcessingException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ClientFilterTest extends JerseyTest {
+
+ @Path("/test")
+ public static class FooResource {
+
+ @GET
+ public String get(@Context HttpHeaders headers) {
+ return "GET "
+ + headers.getHeaderString(HttpHeaders.COOKIE)
+ + headers.getHeaderString(HttpHeaders.CACHE_CONTROL);
+ }
+ }
+
+ public static class CustomRequestFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext clientRequestContext) throws IOException {
+ clientRequestContext.abortWith(Response.ok("OK!", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FooResource.class);
+ }
+
+ @Test
+ public void filterAbortTest() {
+ final WebTarget target = target();
+ target.register(CustomRequestFilter.class);
+ final String entity = target.request().get(String.class);
+
+ assertEquals("OK!", entity);
+ }
+
+ public static class HeaderProvidersRequestFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext clientRequestContext) throws IOException {
+ final CacheControl cacheControl = new CacheControl();
+ cacheControl.setPrivate(true);
+ clientRequestContext.getHeaders().putSingle(HttpHeaders.CACHE_CONTROL, cacheControl);
+ clientRequestContext.getHeaders().putSingle(HttpHeaders.COOKIE, new Cookie("cookie", "cookie-value"));
+ }
+ }
+
+ @Test
+ public void filterHeaderProvidersTest() {
+ final WebTarget target = target();
+ target.register(HeaderProvidersRequestFilter.class).register(LoggingFeature.class);
+ final Response response = target.path("test").request().get(Response.class);
+ final String entity = response.readEntity(String.class);
+
+ assertTrue(entity.contains("GET"));
+ assertTrue(entity.contains("private"));
+ assertTrue(entity.contains("cookie-value"));
+ }
+
+ public static class IOExceptionResponseFilter implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws
+ IOException {
+ throw new IOException(IOExceptionResponseFilter.class.getName());
+
+ }
+ }
+
+ @Test
+ public void ioExceptionResponseFilterTest() {
+ final WebTarget target = target();
+ target.register(IOExceptionResponseFilter.class).register(LoggingFeature.class);
+
+ boolean caught = false;
+
+ try {
+ target.path("test").request().get(Response.class);
+ } catch (ResponseProcessingException e) {
+ caught = true;
+ assertNotNull(e.getCause());
+ assertEquals(IOException.class, e.getCause().getClass());
+ assertEquals(IOExceptionResponseFilter.class.getName(), e.getCause().getMessage());
+ }
+
+ assertTrue(caught);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPathTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPathTest.java
new file mode 100644
index 0000000..ee07bd7
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPathTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test definition of path in client invocation.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class ClientPathTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class, TestResourceWithPathParams.class);
+ }
+
+ /**
+ * Test that {@link PathParam path parameters} can be passed to {@link Client#target(String)} method.
+ */
+ @Test
+ public void pathParamInTargetTest() {
+
+ Response response = client().target("http://localhost:" + getPort() + "/test/{beginBy}")
+ .resolveTemplate("beginBy", "abc")
+ .request(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-get,abc", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests path concatenation. (regression test for JERSEY-1114)
+ */
+ @Test
+ public void pathConcatenationTest1() {
+ Response response = client().target("http://localhost:" + getPort()).path("path").request(MediaType.TEXT_PLAIN_TYPE)
+ .get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-path", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests path concatenation. (regression test for JERSEY-1114)
+ */
+ @Test
+ public void pathConcatenationTest2() {
+ Response response = client().target("http://localhost:" + getPort()).path("/path").request(MediaType.TEXT_PLAIN_TYPE)
+ .get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-path", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests path concatenation. (regression test for JERSEY-1114)
+ */
+ @Test
+ public void pathConcatenationTest3() {
+ Response response = client().target("http://localhost:" + getPort()).path("/path/").path("/another/")
+ .request(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-another-path", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests path concatenation. (regression test for JERSEY-1114)
+ */
+ @Test
+ public void pathConcatenationTest4() {
+ Response response = client().target("http://localhost:" + getPort()).path("/path").path("another/")
+ .request(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-another-path", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests path concatenation. (regression test for JERSEY-1114)
+ */
+ @Test
+ public void pathConcatenationTest6() {
+ Response response = client().target("http://localhost:" + getPort() + "/").path("/path/another")
+ .request(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(200, response.getStatus());
+ assertEquals("test-another-path", response.readEntity(String.class));
+ }
+
+ /**
+ * Test resource class with {@link PathParam path parameters).
+ *
+ */
+ @Path("test/{beginBy}")
+ public static class TestResourceWithPathParams {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String get(@PathParam(value = "beginBy") String param) {
+ return "test-get," + param;
+ }
+
+ }
+
+ /**
+ * Test resource class.
+ *
+ */
+ @Path("path")
+ public static class TestResource {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String get() {
+ return "test-path";
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Path("another")
+ public String getAnother() {
+ return "test-another-path";
+ }
+
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPreInitTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPreInitTest.java
new file mode 100644
index 0000000..ad4d687
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ClientPreInitTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.JerseyWebTarget;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test pre initialization of the client.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ClientPreInitTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Path("resource")
+ public static class Resource {
+ @GET
+ public String get(@HeaderParam("filter-request") String header) {
+ return "resource:" + (header == null ? "<null>" : header);
+ }
+
+ @GET
+ @Path("child")
+ public String getChild(@HeaderParam("filter-request") String header) {
+ return "child:" + (header == null ? "<null>" : header);
+ }
+ }
+
+ public static class MyRequestFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().add("filter-request", "called");
+ }
+ }
+
+ public static class MyResponseFilter implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().add("filter-response", "called");
+ }
+ }
+
+ public static class TestReader implements MessageBodyReader<Integer> {
+ public static boolean initialized;
+
+ public TestReader() {
+ TestReader.initialized = true;
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public Integer readFrom(Class<Integer> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ return null;
+ }
+ }
+
+ @Before
+ public void before() {
+ TestReader.initialized = false;
+ }
+
+ @Test
+ public void testNonInitialized() {
+ Client client = ClientBuilder.newClient();
+ client.register(MyResponseFilter.class);
+ client.register(TestReader.class);
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ assertFalse(TestReader.initialized);
+ final Response resourceResponse = target.request().get();
+ checkResponse(resourceResponse, "resource:<null>");
+ assertTrue(TestReader.initialized);
+ }
+
+ @Test
+ public void testSimplePreinitialize() {
+ Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ target.register(MyResponseFilter.class);
+ final WebTarget childTarget = target.path("child");
+ ((JerseyWebTarget) childTarget).preInitialize();
+ final Response response = childTarget.request().get();
+ checkResponse(response, "child:<null>");
+
+ final Response resourceResponse = target.request().get();
+ checkResponse(resourceResponse, "resource:<null>");
+ }
+
+ @Test
+ public void testReusingPreinitializedConfig() {
+ Client client = ClientBuilder.newClient();
+ client.register(TestReader.class);
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ target.register(MyResponseFilter.class);
+ ((JerseyWebTarget) target).preInitialize();
+ assertTrue(TestReader.initialized);
+ final WebTarget childTarget = target.path("child");
+ final Response response = childTarget.request().get();
+
+ checkResponse(response, "child:<null>");
+
+ final Response resourceResponse = target.request().get();
+ checkResponse(resourceResponse, "resource:<null>");
+ }
+
+ @Test
+ public void testReusingPreinitializedConfig2() {
+ Client client = ClientBuilder.newClient();
+ client.register(TestReader.class);
+ client.register(MyResponseFilter.class);
+
+ assertFalse(TestReader.initialized);
+ ((JerseyClient) client).preInitialize();
+ assertTrue(TestReader.initialized);
+
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ final WebTarget childTarget = target.path("child");
+ final Response response = childTarget.request().get();
+ checkResponse(response, "child:<null>");
+
+ final Response resourceResponse = target.request().get();
+ checkResponse(resourceResponse, "resource:<null>");
+ }
+
+ private void checkResponse(Response response, String entity) {
+ assertEquals("called", response.getHeaders().get("filter-response").get(0));
+ assertEquals(200, response.getStatus());
+ assertEquals(entity, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testRegisterOnPreinitialized1() {
+ Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ target.register(MyRequestFilter.class);
+ ((JerseyWebTarget) target).preInitialize();
+ target.register(MyResponseFilter.class);
+ final Response response = target.request().get();
+ checkResponse(response, "resource:called");
+ }
+
+ @Test
+ public void testRegisterOnPreinitialized2() {
+ Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target(super.getBaseUri()).path("resource");
+ target.register(MyResponseFilter.class);
+ ((JerseyWebTarget) target).preInitialize();
+ final WebTarget child = target.path("child");
+ child.register(MyRequestFilter.class);
+
+ final Response response = target.request().get();
+ checkResponse(response, "resource:<null>");
+
+ final Response childResponse = child.request().get();
+ checkResponse(childResponse, "child:called");
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectHeadTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectHeadTest.java
new file mode 100644
index 0000000..204ca15
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectHeadTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.net.URI;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests that configuration of {@link ClientProperties#FOLLOW_REDIRECTS} works when HEAD method is used.
+ *
+ * @author Paul Sandoz
+ * @author Miroslav Fuksa
+ */
+public class FollowRedirectHeadTest extends JerseyTest {
+
+ @Path("resource")
+ public static class Resource {
+
+ @Path("redirect")
+ @GET
+ public Response redirect() {
+ return Response.status(303).location(URI.create("resource/final")).build();
+ }
+
+ @Path("final")
+ @GET
+ public Response afterRedirection() {
+ return Response.ok("final-entity").build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, LoggingFeature.class);
+ }
+
+ private WebTarget getTarget(boolean followRedirect) {
+ Client client = ClientBuilder.newClient(new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS,
+ followRedirect));
+ return client.target(getBaseUri()).path("resource/redirect");
+ }
+
+ @Test
+ public void testDontFollowRedirectHead() throws Exception {
+ Response response = getTarget(false).request().head();
+ Assert.assertEquals(303, response.getStatus());
+ Assert.assertTrue(response.getLocation().toString().endsWith("/final"));
+ }
+
+ @Test
+ public void testDontFollowRedirectGet() throws Exception {
+ Response response = getTarget(false).request().get();
+ Assert.assertEquals(303, response.getStatus());
+ Assert.assertTrue(response.getLocation().toString().endsWith("/final"));
+ }
+
+ @Test
+ public void testFollowRedirectHead() throws Exception {
+ Response response = getTarget(true).request().head();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertFalse(response.hasEntity());
+ }
+
+ @Test
+ public void testFollowRedirectGet() throws Exception {
+ Response response = getTarget(true).request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("final-entity", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectsTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectsTest.java
new file mode 100644
index 0000000..12610b1
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/FollowRedirectsTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class FollowRedirectsTest extends JerseyTest {
+ @Path("/test")
+ public static class RedirectResource {
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @GET
+ @Path("redirect")
+ public Response redirect() {
+ return Response.seeOther(UriBuilder.fromResource(RedirectResource.class).build()).build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RedirectResource.class);
+ }
+
+ @Test
+ public void testDoFollow() {
+ final Response response = target("test/redirect").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("GET", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testDontFollow() {
+ final WebTarget target = target("test/redirect");
+ target.property(ClientProperties.FOLLOW_REDIRECTS, false);
+ assertEquals(303, target.request().get().getStatus());
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/GenericResponseTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/GenericResponseTest.java
new file mode 100644
index 0000000..14dadcd
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/GenericResponseTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.SyncInvoker;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test {@link GenericType} with {@link Response}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class GenericResponseTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @POST
+ public String post(String post) {
+ return post;
+ }
+ }
+
+ @Test
+ public void testPost() {
+ GenericType<Response> generic = new GenericType<Response>(Response.class);
+ Entity entity = Entity.entity("entity", MediaType.WILDCARD_TYPE);
+
+ WebTarget target = target("resource");
+ SyncInvoker sync = target.request();
+
+ Response response = sync.post(entity, generic);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("entity", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testAsyncPost() throws ExecutionException, InterruptedException {
+ GenericType<Response> generic = new GenericType<Response>(Response.class);
+ Entity entity = Entity.entity("entity", MediaType.WILDCARD_TYPE);
+
+ WebTarget target = target("resource");
+ final AsyncInvoker async = target.request().async();
+
+ Response response = async.post(entity, generic).get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("entity", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGet() {
+ GenericType<Response> generic = new GenericType<Response>(Response.class);
+
+ WebTarget target = target("resource");
+ SyncInvoker sync = target.request();
+ Response response = sync.get(generic);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("get", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testAsyncGet() throws ExecutionException, InterruptedException {
+ GenericType<Response> generic = new GenericType<Response>(Response.class);
+
+ WebTarget target = target("resource");
+ final AsyncInvoker async = target.request().async();
+ Response response = async.get(generic).get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("get", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGetGenericString() {
+ GenericType<String> generic = new GenericType<String>(String.class);
+
+ WebTarget target = target("resource");
+ SyncInvoker sync = target.request();
+ final String entity = sync.get(generic);
+ Assert.assertEquals("get", entity);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpAuthorizationTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpAuthorizationTest.java
new file mode 100644
index 0000000..24d8114
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpAuthorizationTest.java
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.nio.charset.Charset;
+import java.security.Principal;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.internal.util.Base64;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests {@link org.glassfish.jersey.client.authentication.HttpAuthenticationFeature}.
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(ConcurrentRunner.class)
+public class HttpAuthorizationTest extends JerseyTest {
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface Digest {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface Basic {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface Alternating {
+ }
+
+ /**
+ * Alternates between BASIC and DIGEST (each is used for 2 requests).
+ */
+ @Alternating
+ public static class AlternatingDigestBasicFilter implements ContainerRequestFilter {
+
+ int counter = 0;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if ((counter++ / 2) % 2 == 0) {
+ new BasicFilter().filter(requestContext);
+ } else {
+ new DigestFilter().filter(requestContext);
+ }
+ }
+ }
+
+ @Digest
+ public static class DigestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ final String authorization = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
+
+ if (authorization != null && authorization.trim().toUpperCase().startsWith("DIGEST")) {
+ final Matcher match = Pattern.compile("username=\"([^\"]+)\"").matcher(authorization);
+ if (!match.find()) {
+ return;
+ }
+ final String username = match.group(1);
+
+ requestContext.setSecurityContext(new SecurityContext() {
+ @Override
+ public Principal getUserPrincipal() {
+ return new Principal() {
+ @Override
+ public String getName() {
+ return username;
+ }
+ };
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ return false;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ return "DIGEST";
+ }
+ });
+ return;
+ }
+ requestContext.abortWith(Response.status(401).header(HttpHeaders.WWW_AUTHENTICATE,
+ "Digest realm=\"my-realm\", domain=\"\", nonce=\"n9iv3MeSNkEfM3uJt2gnBUaWUbKAljxp\", algorithm=MD5, "
+ + "qop=\"auth\", stale=false")
+ .build());
+ }
+ }
+
+ /**
+ * Basic Auth: password must be the same as user name except first letter is capitalized.
+ * Example: username "homer" -> password "Homer"
+ */
+ @Basic
+ public static class BasicFilter implements ContainerRequestFilter {
+
+ static final Charset CHARACTER_SET = Charset.forName("iso-8859-1");
+ public static final String AUTH_SCHEME_CASE = "Auth-Scheme-Case";
+
+ @Override
+ public void filter(ContainerRequestContext request) throws IOException {
+
+ String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
+ if (authHeader != null && authHeader.trim().toUpperCase().startsWith("BASIC")) {
+ String decoded = new String(Base64.decode(authHeader.substring(6).getBytes()), CHARACTER_SET);
+ // String decoded = Base64.decodeAsString(authHeader.substring(6));
+ final String[] split = decoded.split(":");
+ final String username = split[0];
+ final String pwd = split[1];
+ String capitalizedUserName = username.substring(0, 1).toUpperCase() + username.substring(1);
+ if (capitalizedUserName.equals(pwd)) {
+ request.setSecurityContext(new SecurityContext() {
+ @Override
+ public Principal getUserPrincipal() {
+ return new Principal() {
+ @Override
+ public String getName() {
+ return username;
+ }
+ };
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ return true;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ return "BASIC";
+ }
+ });
+ return;
+ }
+ }
+ final String authSchemeCase = request.getHeaderString(AUTH_SCHEME_CASE);
+
+ final String authScheme;
+ if ("uppercase".equals(authSchemeCase)) {
+ authScheme = "BASIC";
+ } else if ("lowercase".equals(authSchemeCase)) {
+ authScheme = "basic";
+ } else {
+ authScheme = "Basic";
+ }
+
+ request.abortWith(Response.status(401).header(HttpHeaders.WWW_AUTHENTICATE, authScheme).build());
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
+ resourceConfig.register(LoggingFeature.class);
+ resourceConfig.register(new BasicFilter());
+ resourceConfig.register(new DigestFilter());
+ resourceConfig.register(new AlternatingDigestBasicFilter());
+ return resourceConfig;
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @Context
+ SecurityContext securityContext;
+
+ @GET
+ public String unsecure() {
+ return "unsecure";
+ }
+
+ @GET
+ @Path("basic")
+ @Basic
+ public String basic() {
+ return securityContext.getAuthenticationScheme() + ":" + securityContext.getUserPrincipal().getName();
+ }
+
+ @GET
+ @Path("digest")
+ @Digest
+ public String digest() {
+ return securityContext.getAuthenticationScheme() + ":" + securityContext.getUserPrincipal().getName();
+ }
+
+ @GET
+ @Path("alternating")
+ @Alternating
+ public String alternating() {
+ return securityContext.getAuthenticationScheme() + ":" + securityContext.getUserPrincipal().getName();
+ }
+
+ }
+
+ @Test
+ public void testBasicPreemptive() {
+ Response response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.basicBuilder().credentials("homer", "Homer").build())
+ .request().get();
+ check(response, 200, "BASIC:homer");
+ }
+
+ @Test
+ public void testBasicNonPreemptive() {
+ Response response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.basicBuilder().nonPreemptive().credentials("homer", "Homer").build())
+ .request().get();
+ check(response, 200, "BASIC:homer");
+ }
+
+ @Test
+ public void testBasicNonPreemptiveWithEmptyPassword() {
+ final WebTarget target = target().path("resource")
+ .register(HttpAuthenticationFeature.basicBuilder().nonPreemptive().build());
+ Response response = target.request().get();
+ check(response, 200, "unsecure");
+
+ try {
+ response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.basicBuilder().nonPreemptive().build())
+ .request().get();
+ Assert.fail("should throw an exception as credentials are missing");
+ } catch (Exception e) {
+ // ok
+ }
+
+ response = target.path("basic").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "Bart")
+ .get();
+
+ check(response, 200, "BASIC:bart");
+ }
+
+ @Test
+ public void testUniversalBasic() {
+ Response response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build())
+ .request().get();
+ check(response, 200, "BASIC:homer");
+ }
+
+ /**
+ * Reproducer for JERSEY-2941: BasicAuthenticator#filterResponseAndAuthenticate: auth-scheme checks should be case
+ * insensitve.
+ */
+ @Test
+ public void testUniversalBasicCaseSensitivity() {
+ Response response;
+
+ response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build())
+ .request()
+ // no AUTH_SCHEME_CASE header = mixed case
+ .get();
+ check(response, 200, "BASIC:homer");
+
+ response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build())
+ .request()
+ .header(BasicFilter.AUTH_SCHEME_CASE, "lowercase")
+ .get();
+ check(response, 200, "BASIC:homer");
+
+ response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build())
+ .request()
+ .header(BasicFilter.AUTH_SCHEME_CASE, "uppercase")
+ .get();
+ check(response, 200, "BASIC:homer");
+ }
+
+ @Test
+ public void testUniversalBasicWrongPassword() {
+ Response response = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "FOO").build())
+ .request().get();
+ check(response, 401);
+ }
+
+ @Test
+ public void testBasicWithDifferentCredentials() {
+ final WebTarget target = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.basicBuilder().credentials("marge", "Marge").build());
+
+ _testBasicWithDifferentCredentials(target);
+ }
+
+ @Test
+ public void testBasicUniversalWithDifferentCredentials() {
+ final WebTarget target = target().path("resource").path("basic")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("marge", "Marge").build());
+
+ _testBasicWithDifferentCredentials(target);
+ }
+
+ public void _testBasicWithDifferentCredentials(WebTarget target) {
+ Response response = target
+ .request().get();
+ check(response, 200, "BASIC:marge");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart")
+ .get();
+
+ check(response, 200, "BASIC:bart");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "Bart")
+ .get();
+
+ check(response, 200, "BASIC:bart");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart")
+ .get();
+
+ check(response, 200, "BASIC:marge");
+ }
+
+ @Test
+ public void testDigest() {
+ Response response = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.digest("homer", "Homer"))
+ .request().get();
+ check(response, 200, "DIGEST:homer");
+ }
+
+ @Test
+ public void testDigestWithPasswords() {
+ final WebTarget target = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.digest("homer", "Homer"));
+ _testDigestWithPasswords(target);
+ }
+
+ @Test
+ public void testUniversalDigestWithPasswords() {
+ final WebTarget target = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build());
+ _testDigestWithPasswords(target);
+ }
+
+ public void _testDigestWithPasswords(WebTarget target) {
+ Response response = target.request().get();
+ check(response, 200, "DIGEST:homer");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "DIGEST:bart");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "DIGEST:homer");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "DIGEST:bart");
+ }
+
+ @Test
+ public void testDigestWithEmptyDefaultPassword() {
+ final WebTarget target = target().path("resource")
+ .register(HttpAuthenticationFeature.digest());
+ _testDigestWithEmptyDefaultPassword(target);
+ }
+
+ @Test
+ public void testDigestUniversalWithEmptyDefaultPassword() {
+ final WebTarget target = target().path("resource")
+ .register(HttpAuthenticationFeature.universalBuilder().build());
+ _testDigestWithEmptyDefaultPassword(target);
+ }
+
+ public void _testDigestWithEmptyDefaultPassword(WebTarget target) {
+ Response response = target.request().get();
+ check(response, 200, "unsecure");
+
+ response = target.request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "unsecure");
+
+ response = target.path("digest").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "DIGEST:bart");
+
+ try {
+ target.path("digest").request()
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "Bart")
+ .get();
+ Assert.fail("should throw an exception as no credentials were supplied for digest auth");
+ } catch (Exception e) {
+ // ok
+ }
+
+ response = target.path("digest").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart")
+ .get();
+ check(response, 200, "DIGEST:bart");
+ }
+
+ private void check(Response response, int status, String entity) {
+ Assert.assertEquals(status, response.getStatus());
+ Assert.assertEquals(entity, response.readEntity(String.class));
+ }
+
+ private void check(Response response, int status) {
+ Assert.assertEquals(status, response.getStatus());
+ }
+
+ @Test
+ public void testDigestUniversalSimple() {
+ Response response = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.universalBuilder().credentials("homer", "Homer").build())
+ .request().get();
+ check(response, 200, "DIGEST:homer");
+ }
+
+ @Test
+ public void testDigestUniversalSimple2() {
+ Response response = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.universalBuilder().credentialsForDigest("homer", "Homer").build())
+ .request().get();
+ check(response, 200, "DIGEST:homer");
+ }
+
+ @Test
+ public void testDigestUniversalSimple3() {
+ Response response = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.universalBuilder()
+ .credentialsForDigest("homer", "Homer")
+ .credentialsForBasic("foo", "bar")
+ .build())
+ .request().get();
+ check(response, 200, "DIGEST:homer");
+ }
+
+ @Test
+ public void testDigestUniversalSimple4() {
+ Response response = target().path("resource").path("digest")
+ .register(HttpAuthenticationFeature.universal("homer", "Homer"))
+ .request().get();
+ check(response, 200, "DIGEST:homer");
+ }
+
+ @Test
+ public void testUniversal() {
+ final WebTarget target = target().path("resource")
+ .register(HttpAuthenticationFeature.universal("homer", "Homer"));
+
+ check(target.request().get(), 200, "unsecure");
+ check(target.path("digest").request().get(), 200, "DIGEST:homer");
+ check(target.path("basic").request().get(), 200, "BASIC:homer");
+ check(target.path("basic").request().get(), 200, "BASIC:homer");
+ check(target.path("digest").request().get(), 200, "DIGEST:homer");
+ check(target.path("digest").request().get(), 200, "DIGEST:homer");
+ check(target.path("digest").request().get(), 200, "DIGEST:homer");
+ check(target.path("basic").request().get(), 200, "BASIC:homer");
+ check(target.path("basic").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart").get(), 200, "BASIC:homer");
+
+ check(target.path("digest").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_DIGEST_PASSWORD, "Bart").get(), 200, "DIGEST:bart");
+
+ check(target.path("digest").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart").get(), 200, "DIGEST:bart");
+
+ check(target.path("alternating").request().get(), 200, "BASIC:homer");
+ check(target.path("alternating").request().get(), 200, "DIGEST:homer");
+ check(target.path("alternating").request().get(), 200, "BASIC:homer");
+ check(target.path("basic").request().get(), 200, "BASIC:homer");
+ check(target.path("alternating").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart").get(), 200, "DIGEST:bart");
+ check(target.path("alternating").request().property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME, "bart")
+ .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD, "Bart").get(), 200, "BASIC:bart");
+
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpDigestAuthFilterTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpDigestAuthFilterTest.java
new file mode 100644
index 0000000..14aaee9
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpDigestAuthFilterTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.uri.UriComponent;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Stefan Katerkamp <stefan at katerkamp.de>
+ */
+public class HttpDigestAuthFilterTest extends JerseyTest {
+
+ private static final String DIGEST_TEST_LOGIN = "user";
+ private static final String DIGEST_TEST_PASS = "password";
+ private static final String DIGEST_TEST_INVALIDPASS = "nopass";
+ // Digest string expected for OK auth:
+ // Digest realm="test", nonce="eDePFNeJBAA=a874814ec55647862b66a747632603e5825acd39",
+ // algorithm=MD5, domain="/auth-digest/", qop="auth"
+ private static final String DIGEST_TEST_NONCE = "eDePFNeJBAA=a874814ec55647862b66a747632603e5825acd39";
+ private static final String DIGEST_TEST_REALM = "test";
+ private static final String DIGEST_TEST_DOMAIN = "/auth-digest/";
+ private static int ncExpected = 1;
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Path("/auth-digest")
+ public static class Resource {
+
+ @Context
+ private HttpHeaders httpHeaders;
+ @Context
+ private UriInfo uriInfo;
+
+ @GET
+ public Response get1() {
+ return verify();
+ }
+
+
+ @GET
+ @Path("ěščřžýáíé")
+ public Response getEncoding() {
+ return verify();
+ }
+
+ private Response verify() {
+ if (httpHeaders.getRequestHeader(HttpHeaders.AUTHORIZATION) == null) {
+ // the first request has no authorization header, tell filter its 401
+ // and send filter back seed for the new to be built header
+ ResponseBuilder responseBuilder = Response.status(Response.Status.UNAUTHORIZED);
+ responseBuilder = responseBuilder.header(HttpHeaders.WWW_AUTHENTICATE,
+ "Digest realm=\"" + DIGEST_TEST_REALM + "\", "
+ + "nonce=\"" + DIGEST_TEST_NONCE + "\", "
+ + "algorithm=MD5, "
+ + "domain=\"" + DIGEST_TEST_DOMAIN + "\", qop=\"auth\"");
+ return responseBuilder.build();
+ } else {
+ // the filter takes the seed and adds the header
+ final List<String> authList = httpHeaders.getRequestHeader(HttpHeaders.AUTHORIZATION);
+ if (authList.size() != 1) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ final String authHeader = authList.get(0);
+
+ final String ha1 = md5(DIGEST_TEST_LOGIN, DIGEST_TEST_REALM, DIGEST_TEST_PASS);
+ final String requestUri = UriComponent.fullRelativeUri(uriInfo.getRequestUri());
+ final String ha2 = md5("GET", requestUri.startsWith("/") ? requestUri : "/" + requestUri);
+ final String response = md5(
+ ha1,
+ DIGEST_TEST_NONCE,
+ getDigestAuthHeaderValue(authHeader, "nc="),
+ getDigestAuthHeaderValue(authHeader, "cnonce="),
+ getDigestAuthHeaderValue(authHeader, "qop="),
+ ha2);
+
+ // this generates INTERNAL_SERVER_ERROR if not matching
+ Assert.assertEquals(ncExpected, Integer.parseInt(getDigestAuthHeaderValue(authHeader, "nc=")));
+
+ if (response.equals(getDigestAuthHeaderValue(authHeader, "response="))) {
+ return Response.ok().build();
+ } else {
+ return Response.status(Response.Status.UNAUTHORIZED).build();
+ }
+ }
+ }
+
+ private static final Charset CHARACTER_SET = Charset.forName("iso-8859-1");
+
+ /**
+ * Colon separated value MD5 hash. Call md5 method of the filter.
+ *
+ * @param tokens one or more strings
+ * @return M5 hash string
+ */
+ static String md5(final String... tokens) {
+ final StringBuilder sb = new StringBuilder(100);
+ for (final String token : tokens) {
+ if (sb.length() > 0) {
+ sb.append(':');
+ }
+ sb.append(token);
+ }
+
+ final MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (final NoSuchAlgorithmException ex) {
+ throw new ProcessingException(ex.getMessage());
+ }
+ md.update(sb.toString().getBytes(CHARACTER_SET), 0, sb.length());
+ final byte[] md5hash = md.digest();
+ return bytesToHex(md5hash);
+ }
+
+ /**
+ * Convert bytes array to hex string.
+ *
+ * @param bytes array of bytes
+ * @return hex string
+ */
+ private static String bytesToHex(final byte[] bytes) {
+ final char[] hexChars = new char[bytes.length * 2];
+ int v;
+ for (int j = 0; j < bytes.length; j++) {
+ v = bytes[j] & 0xFF;
+ hexChars[j * 2] = HEX_ARRAY[v >>> 4];
+ hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ private static final char[] HEX_ARRAY = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+
+ /**
+ * Get a value of the Digest Auth Header.
+ *
+ * @param authHeader digest auth header string
+ * @param keyName key of the value to retrieve
+ * @return value string
+ */
+ static String getDigestAuthHeaderValue(final String authHeader, final String keyName) {
+ final int i1 = authHeader.indexOf(keyName);
+
+ if (i1 == -1) {
+ return null;
+ }
+
+ String value = authHeader.substring(
+ authHeader.indexOf('=', i1) + 1,
+ (authHeader.indexOf(',', i1) != -1
+ ? authHeader.indexOf(',', i1) : authHeader.length()));
+
+ value = value.trim();
+ if (value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"') {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ return value;
+ }
+ }
+
+ @Test
+ public void testHttpDigestAuthFilter() {
+ testRequest("auth-digest");
+ }
+
+ @Test
+ public void testHttpDigestAuthFilterWithEncodedUri() {
+ testRequest("auth-digest/ěščřžýáíé");
+ }
+
+ @Test
+ public void testHttpDigestAuthFilterWithParams() {
+ testRequest("auth-digest", true);
+ }
+
+ @Test
+ public void testHttpDigestAuthFilterWithEncodedUriAndParams() {
+ testRequest("auth-digest/ěščřžýáíé", true);
+ }
+
+ private void testRequest(final String path) {
+ testRequest(path, false);
+ }
+
+ private void testRequest(final String path, final boolean addParams) {
+ WebTarget resource = target()
+ .register(HttpAuthenticationFeature.digest(DIGEST_TEST_LOGIN, DIGEST_TEST_PASS))
+ .path(path);
+
+ if (addParams) {
+ resource = resource.matrixParam("bar", "foo").queryParam("foo", "bar");
+ }
+
+ ncExpected = 1;
+ final Response r1 = resource.request().get();
+ Assert.assertEquals(Response.Status.fromStatusCode(r1.getStatus()), Response.Status.OK);
+ }
+
+
+ @Test
+ public void testPreemptive() {
+ final WebTarget resource = target()
+ .register(HttpAuthenticationFeature.digest(DIGEST_TEST_LOGIN, DIGEST_TEST_PASS))
+ .path("auth-digest");
+
+ ncExpected = 1;
+ final Response r1 = resource.request().get();
+ Assert.assertEquals(Response.Status.fromStatusCode(r1.getStatus()), Response.Status.OK);
+
+ ncExpected = 2;
+ final Response r2 = resource.request().get();
+ Assert.assertEquals(Response.Status.fromStatusCode(r2.getStatus()), Response.Status.OK);
+
+ ncExpected = 3;
+ final Response r3 = resource.request().get();
+ Assert.assertEquals(Response.Status.fromStatusCode(r3.getStatus()), Response.Status.OK);
+
+ }
+
+ @Test
+ public void testAuthentication() {
+ final WebTarget resource = target()
+ .register(HttpAuthenticationFeature.digest(DIGEST_TEST_LOGIN, DIGEST_TEST_INVALIDPASS))
+ .path("auth-digest");
+
+ ncExpected = 1;
+ final Response r1 = resource.request().get();
+ Assert.assertEquals(Response.Status.fromStatusCode(r1.getStatus()), Response.Status.UNAUTHORIZED);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpMethodEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpMethodEntityTest.java
new file mode 100644
index 0000000..546fd54
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpMethodEntityTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.util.concurrent.Future;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests HTTP methods and entity presence.
+ *
+ * @author Miroslav Fuksa
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class HttpMethodEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testGet() {
+ _test("GET", true, true);
+ _test("GET", false, false);
+ }
+
+ @Test
+ public void testPost() {
+ _test("POST", true, false);
+ _test("POST", false, false);
+ }
+
+ @Test
+ public void testPut() {
+ _test("PUT", true, false);
+ _test("PUT", false, true);
+ }
+
+ @Test
+ public void testDelete() {
+ _test("DELETE", true, true);
+ _test("DELETE", false, false);
+ }
+
+ @Test
+ public void testHead() {
+ _test("HEAD", true, true);
+ _test("HEAD", false, false);
+ }
+
+ @Test
+ public void testOptions() {
+ _test("OPTIONS", true, true);
+ _test("OPTIONS", false, false);
+ }
+
+ /**
+ * Reproducer for JERSEY-2370: Sending POST without body.
+ */
+ @Test
+ public void testEmptyPostWithoutContentType() {
+ final WebTarget resource = target().path("resource");
+ try {
+ final Future<Response> future = resource.request().async().post(null);
+ assertEquals(200, future.get().getStatus());
+
+ final Response response = resource.request().post(null);
+ assertEquals(200, response.getStatus());
+ } catch (Exception e) {
+ fail("Sending POST method without entity should not fail.");
+ }
+ }
+
+ /**
+ * Reproducer for JERSEY-2370: Sending POST without body.
+ */
+ @Test
+ public void testEmptyPostWithContentType() {
+ final WebTarget resource = target().path("resource");
+ try {
+ final Future<Response> future = resource.request().async().post(Entity.entity(null, "text/plain"));
+ assertEquals(200, future.get().getStatus());
+
+ final Response response = resource.request().post(Entity.entity(null, "text/plain"));
+ assertEquals(200, response.getStatus());
+ } catch (Exception e) {
+ fail("Sending POST method without entity should not fail.");
+ }
+ }
+
+ public void _test(String method, boolean entityPresent, boolean shouldFail) {
+ Entity entity = entityPresent ? Entity.entity("entity", MediaType.TEXT_PLAIN_TYPE) : null;
+ _testSync(method, entity, shouldFail);
+ _testAsync(method, entity, shouldFail);
+ }
+
+ public void _testAsync(String method, Entity entity, boolean shouldFail) {
+ try {
+ final Future<Response> future = target().path("resource").request().async().method(method, entity);
+ if (shouldFail) {
+ fail("The method should fail.");
+ }
+ assertEquals(200, future.get().getStatus());
+ } catch (Exception e) {
+ if (!shouldFail) {
+ fail("The method " + method + " with entity=" + (entity != null) + " should not fail.");
+ }
+ }
+ }
+
+ public void _testSync(String method, Entity entity, boolean shouldFail) {
+ try {
+ final Response response = target().path("resource").request().method(method, entity);
+ assertEquals(200, response.getStatus());
+ if (shouldFail) {
+ fail("The method should fail.");
+ }
+ } catch (Exception e) {
+ if (!shouldFail) {
+ fail("The method " + method + " with entityPresent=" + (entity != null) + " should not fail.");
+ }
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @Context
+ HttpHeaders httpHeaders;
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @POST
+ public String post(String str) {
+ // See JERSEY-1455
+ assertFalse(httpHeaders.getRequestHeaders().containsKey(HttpHeaders.CONTENT_ENCODING));
+ assertFalse(httpHeaders.getRequestHeaders().containsKey(HttpHeaders.CONTENT_LANGUAGE));
+
+ return "post";
+ }
+
+ @PUT
+ public String put(String str) {
+ return "put";
+ }
+
+ @HEAD
+ public String head() {
+ return "head";
+ }
+
+ @DELETE
+ public String delete() {
+ return "delete";
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java
new file mode 100644
index 0000000..37e544c
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test if JAX-RS injection points work in client side providers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InjectedClientBodyWorker extends JerseyTest {
+
+ // media types are used to determine what kind of injection should be tested
+ static final String ProviderType = "test/providers";
+ static final String ConfigurationTYPE = "test/configuration";
+
+ public static class MyContext {}
+
+ @Provider
+ public static class MyContextResolver implements ContextResolver<MyContext> {
+
+ @Override
+ public MyContext getContext(Class<?> type) {
+ return null;
+ }
+ }
+
+ @Provider
+ @Produces(ProviderType)
+ public static class ProvidersInjectedWriter implements MessageBodyWriter<String> {
+
+ @Context
+ Providers providers;
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(String t, Class<?> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+
+ // make sure no exception occurs here
+ providers.getExceptionMapper(Exception.class);
+
+ final ContextResolver<MyContext> contextResolver = providers
+ .getContextResolver(MyContext.class, MediaType.valueOf(ProviderType));
+ entityStream.write(String.format("%s", contextResolver).getBytes());
+ }
+ }
+
+ @Provider
+ @Consumes(ProviderType)
+ public static class ProvidersInjectedReader implements MessageBodyReader<String> {
+
+ @Context
+ Providers providers;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ // make sure no exception occurs here
+ providers.getExceptionMapper(Exception.class);
+
+ final ContextResolver<MyContext> contextResolver = providers
+ .getContextResolver(MyContext.class, MediaType.valueOf(ProviderType));
+ return String.format("%s", contextResolver);
+ }
+
+ }
+
+ @Provider
+ @Produces(ConfigurationTYPE)
+ public static class ConfigurationInjectedWriter implements MessageBodyWriter<String> {
+
+ @Context
+ Configuration configuration;
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(String t, Class<?> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+
+ final boolean ctxResolverRegistered = configuration.isRegistered(MyContextResolver.class);
+ entityStream.write(String.format("%b", ctxResolverRegistered).getBytes());
+ }
+ }
+
+ @Provider
+ @Consumes(ConfigurationTYPE)
+ public static class ConfigurationInjectedReader implements MessageBodyReader<String> {
+
+ @Context
+ Configuration configuration;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ final boolean ctxResolverRegistered = configuration.isRegistered(MyContextResolver.class);
+ return String.format("%b", ctxResolverRegistered);
+ }
+ }
+
+ @Path("echo")
+ public static class EchoResource {
+
+ @POST
+ @Consumes({ProviderType, ConfigurationTYPE, MediaType.TEXT_PLAIN})
+ @Produces({ProviderType, ConfigurationTYPE, MediaType.TEXT_PLAIN})
+ public String post(String p) {
+ return p;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(EchoResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config
+ .register(ProvidersInjectedWriter.class)
+ .register(ConfigurationInjectedWriter.class)
+ .register(ProvidersInjectedReader.class)
+ .register(ConfigurationInjectedReader.class);
+ }
+
+ @Test
+ public void testProvidersInReader() throws Exception {
+ _testProviders(ProviderType, MediaType.TEXT_PLAIN);
+ }
+
+ @Test
+ public void testProvidersInWriter() throws Exception {
+ _testProviders(MediaType.TEXT_PLAIN, ProviderType);
+ }
+
+ @Test
+ public void testConfigurationInReader() throws Exception {
+ testConfiguration(ConfigurationTYPE, MediaType.TEXT_PLAIN);
+ }
+
+ @Test
+ public void testConfigurationInWriter() throws Exception {
+ testConfiguration(MediaType.TEXT_PLAIN, ConfigurationTYPE);
+ }
+
+ private void _testProviders(final String incomingType, final String outgoingType) throws Exception {
+
+ final String postWithoutProviderResult = target("echo")
+ .request(outgoingType)
+ .post(Entity.entity("does not matter", incomingType), String.class);
+ assertThat(postWithoutProviderResult, is("null"));
+
+ final String postWithProviderResult = target("echo")
+ .register(MyContextResolver.class)
+ .request(outgoingType)
+ .post(Entity.entity("ignored", incomingType), String.class);
+ assertThat(postWithProviderResult, containsString(MyContextResolver.class.getName()));
+ }
+
+ private void testConfiguration(final String incomingType, final String outgoingType) throws Exception {
+
+ final String postWithoutProviderResult = target("echo")
+ .request(incomingType)
+ .post(Entity.entity("whatever", outgoingType), String.class);
+ assertThat(postWithoutProviderResult, is("false"));
+
+ final String postWithProviderResult = target("echo")
+ .register(MyContextResolver.class)
+ .request(incomingType)
+ .post(Entity.entity("bummer", outgoingType), String.class);
+ assertThat(postWithProviderResult, is("true"));
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectionManagerProviderTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectionManagerProviderTest.java
new file mode 100644
index 0000000..6ee393e
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectionManagerProviderTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.InjectionManagerProvider;
+import org.glassfish.jersey.client.InjectionManagerClientProvider;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link InjectionManagerClientProvider}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class InjectionManagerProviderTest extends JerseyTest {
+
+ @Path("resource")
+ public static class TestResource {
+ @POST
+ public String echo(String entity) {
+ return entity;
+ }
+ }
+
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+
+ public static class MyInjectedService {
+ public final String name;
+
+ public MyInjectedService(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public static class BinderFeature implements Feature {
+
+ public final String name;
+
+ public BinderFeature(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjectedService(name)).to(MyInjectedService.class);
+ }
+ });
+ return true;
+ }
+ }
+
+
+ public static class MyRequestFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ final InjectionManager injectionManager = InjectionManagerClientProvider.getInjectionManager(requestContext);
+ final MyInjectedService service = injectionManager.getInstance(MyInjectedService.class);
+ final String name = service.getName();
+ requestContext.setEntity(name);
+ }
+ }
+
+
+ @Test
+ public void testRequestFilterInstance() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("hello"))
+ .register(new MyRequestFilter())
+ .request().post(Entity.entity("will-be-overwritten", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("hello", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testRequestFilterClass() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("hello"))
+ .register(MyRequestFilter.class)
+ .request().post(Entity.entity("will-be-overwritten", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("hello", response.readEntity(String.class));
+ }
+
+
+ public static class MyResponseFilter implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+
+ final InjectionManager locator = InjectionManagerClientProvider.getInjectionManager(responseContext);
+ final MyInjectedService service = locator.getInstance(MyInjectedService.class);
+ final String name = service.getName();
+ responseContext.setEntityStream(new ByteArrayInputStream(name.getBytes()));
+ }
+ }
+
+ @Test
+ public void testResponseFilterInstance() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("world"))
+ .register(new MyResponseFilter())
+ .request().post(Entity.entity("will-be-overwritten", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("world", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResponseFilterClass() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("world"))
+ .register(MyResponseFilter.class)
+ .request().post(Entity.entity("will-be-overwritten", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("world", response.readEntity(String.class));
+ }
+
+ public static class MyFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(MyFeatureInterceptor.class);
+ return true;
+ }
+
+ public static class MyFeatureInterceptor implements WriterInterceptor {
+ private final String name;
+
+ @Inject
+ public MyFeatureInterceptor(MyInjectedService injectedService) {
+ this.name = injectedService.getName();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-interceptor-" + name);
+ context.proceed();
+ }
+ }
+ }
+
+ @Test
+ public void testFeatureInstance() {
+ final Response response = target().path("resource")
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjectedService("feature")).to(MyInjectedService.class);
+ }
+ })
+ .register(new MyFeature())
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-interceptor-feature", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testFeatureClass() {
+ final Response response = target().path("resource")
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjectedService("feature")).to(MyInjectedService.class);
+ }
+ })
+ .register(MyFeature.class)
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-interceptor-feature", response.readEntity(String.class));
+ }
+
+
+ public static class MyWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final InjectionManager serviceLocator = InjectionManagerProvider.getInjectionManager(context);
+ final MyInjectedService service = serviceLocator.getInstance(MyInjectedService.class);
+ context.setEntity(((String) context.getEntity()) + "-writer-interceptor-" + service.getName());
+ context.proceed();
+ }
+ }
+
+ @Test
+ public void testWriterInterceptorInstance() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("universe"))
+ .register(new MyWriterInterceptor())
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-writer-interceptor-universe", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testWriterInterceptorClass() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("universe"))
+ .register(MyWriterInterceptor.class)
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-writer-interceptor-universe", response.readEntity(String.class));
+ }
+
+
+ public static class MyReaderInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final Object entity = context.proceed();
+ if (!(entity instanceof String)) {
+ return entity;
+ }
+ final String stringEntity = (String) entity;
+ final InjectionManager serviceLocator = InjectionManagerProvider.getInjectionManager(context);
+ final MyInjectedService service = serviceLocator.getInstance(MyInjectedService.class);
+ return stringEntity + "-reader-interceptor-" + service.getName();
+ }
+ }
+
+
+ @Test
+ public void testReaderInterceptorInstance() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("universe"))
+ .register(new MyReaderInterceptor())
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-reader-interceptor-universe", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testReaderInterceptorClass() {
+ final Response response = target().path("resource")
+ .register(new BinderFeature("universe"))
+ .register(MyReaderInterceptor.class)
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-reader-interceptor-universe", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/JaxRsTimeoutTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/JaxRsTimeoutTest.java
new file mode 100644
index 0000000..63df9a2
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/JaxRsTimeoutTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.net.SocketTimeoutException;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.JerseyWebTarget;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class JaxRsTimeoutTest extends JerseyTest {
+
+ private final Client client =
+ ClientBuilder.newBuilder().readTimeout(2000, TimeUnit.MILLISECONDS).build();
+
+ @Path("/test")
+ public static class TimeoutResource {
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @GET
+ @Path("timeout")
+ public String getTimeout() {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return "GET";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TimeoutTest.TimeoutResource.class);
+ }
+
+ @Override
+ protected Client getClient() {
+ return client;
+ }
+
+ @Test
+ public void testFast() {
+ Response r = target("test").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("GET", r.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlow() {
+ try {
+ target("test/timeout").request().get();
+ fail("Timeout expected.");
+ } catch (ProcessingException e) {
+ if (!(e.getCause() instanceof SocketTimeoutException)) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonSuccessfulResponseTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonSuccessfulResponseTest.java
new file mode 100644
index 0000000..9075628
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonSuccessfulResponseTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.SyncInvoker;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test no successful (3XX, 4XX, 5XX) responses with no empty body.
+ *
+ * @author Ballesi Ezequiel (ezequielballesi at gmail.com)
+ */
+public class NonSuccessfulResponseTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ // NOTE: This is not necessary when using connector, that does not follow redirects by default, such as HttpUrlConnector.
+ // However, the testcase would fail when FOLLOW_REDIRECTS is set to true. Therefor, we configure the behaviour on
+ // redirects explicitly.
+ config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @GET
+ @Path("/{status}")
+ public Response getXXX(@PathParam("status") int status) {
+ return Response.status(status).entity("get").build();
+ }
+
+ @POST
+ @Path("/{status}")
+ public Response postXXX(@PathParam("status") int status, String post) {
+ return Response.status(status).entity(post).build();
+ }
+
+ }
+
+ @Test
+ public void testGet3XX() {
+ generalTestGet(302);
+ }
+
+ @Test
+ public void testPost3XX() {
+ generalTestPost(302);
+ }
+
+ @Test
+ public void testGet4XX() {
+ generalTestGet(401);
+ }
+
+ @Test
+ public void testPost4XX() {
+ generalTestPost(401);
+ }
+
+ @Test
+ public void testGet5XX() {
+ generalTestGet(500);
+ }
+
+ @Test
+ public void testPost5XX() {
+ generalTestPost(500);
+ }
+
+ private void generalTestGet(int status) {
+ WebTarget target = target("resource").path(Integer.toString(status));
+ SyncInvoker sync = target.request();
+ Response response = sync.get(Response.class);
+ Assert.assertEquals(status, response.getStatus());
+ Assert.assertEquals("get", response.readEntity(String.class));
+ }
+
+ private void generalTestPost(int status) {
+ Entity<String> entity = Entity.entity("entity", MediaType.WILDCARD_TYPE);
+ WebTarget target = target("resource").path(Integer.toString(status));
+ SyncInvoker sync = target.request();
+ Response response = sync.post(entity, Response.class);
+ Assert.assertEquals(status, response.getStatus());
+ Assert.assertEquals("entity", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java
new file mode 100644
index 0000000..b30880d
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * TODO: javadoc.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class RequestScopedReadEntityTest extends JerseyTest {
+
+ public static class Message {
+
+ private final String text;
+
+ public Message(String text) {
+ this.text = text;
+ }
+ }
+
+ @Path("simple")
+ public static class SimpleResource {
+
+ @GET
+ @Produces("text/plain")
+ public String getIt() {
+ return "passed";
+ }
+ }
+
+ @Produces("text/plain")
+ public static class ScopedMessageEntityProvider extends AbstractMessageReaderWriterProvider<Message> {
+
+ @Inject
+ private Provider<ClientRequest> clientRequestProvider;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == Message.class && mediaType.equals(MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ @Override
+ public Message readFrom(
+ Class<Message> type,
+ Type genericType, Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return clientRequestProvider.get() != null
+ ? new Message(readFromAsString(entityStream, mediaType)) : new Message("failed");
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == Message.class && mediaType.equals(MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ @Override
+ public void writeTo(
+ Message message,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ writeToAsString((clientRequestProvider.get() != null) ? message.text : "failed", entityStream, mediaType);
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SimpleResource.class);
+ }
+
+ @Test
+ public void testReadAfterClose() {
+ final Invocation.Builder request = target().path("simple").register(ScopedMessageEntityProvider.class).request();
+
+ final Response response = request.get(Response.class);
+ // reading entity "out-of-scope"
+ final Message msg = response.readEntity(Message.class);
+ assertEquals("passed", msg.text);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseCloseTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseCloseTest.java
new file mode 100644
index 0000000..48ab839
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseCloseTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * Test for Response.close() method.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ResponseCloseTest extends JerseyTest {
+
+ @Path("simple")
+ public static class SimpleResource {
+
+ @GET
+ @Produces("text/plain")
+ public String getIt() {
+ return "it";
+ }
+
+ @GET
+ @Path("empty")
+ public Response getEmpty() {
+ return Response.noContent().build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SimpleResource.class);
+ }
+
+ @Test
+ public void testReadAfterClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.close();
+ try {
+ response.readEntity(String.class);
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testCloseBeforeReadingEmptyContentHasNoEffect() {
+ final Response response = target().path("simple").path("empty").request().get(Response.class);
+ response.close();
+ try {
+ response.readEntity(String.class);
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testReadAfterMultipleClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.close();
+ response.close();
+ response.close();
+ try {
+ response.readEntity(String.class);
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testReadBufferedEntityAfterClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.bufferEntity();
+ response.close();
+ try {
+ response.readEntity(String.class);
+ fail("IllegalStateException expected when reading a buffered entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testBufferEntityAfterClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.close();
+ try {
+ response.bufferEntity();
+ fail("IllegalStateException expected when reading a buffered entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testGetEntityAfterClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.close();
+ try {
+ response.getEntity();
+ fail("IllegalStateException expected when reading a buffered entity after response has been closed.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testHasEntityAfterClose() {
+ final Response response = target().path("simple").request().get(Response.class);
+ response.close();
+ try {
+ response.hasEntity();
+ fail("IllegalStateException should have been caught inside hasEntity.");
+ } catch (final IllegalStateException ex) {
+ // expected
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java
new file mode 100644
index 0000000..c9ddfae
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Buffered response entity tests.
+ *
+ * @author Michal Gajdos
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ResponseReadAndBufferEntityTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(ResponseReadAndBufferEntityTest.class.getName());
+
+ public static class CorruptableInputStream extends InputStream {
+
+ private final AtomicInteger closeCounter = new AtomicInteger(0);
+
+ private boolean corruptClose = false;
+ private boolean corruptRead = false;
+
+ private final ByteArrayInputStream delegate;
+
+ public CorruptableInputStream() {
+ this.delegate = new ByteArrayInputStream(Resource.ENTITY.getBytes());
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+ if (corruptRead) {
+ corrupt();
+ }
+ return delegate.read();
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ if (corruptRead) {
+ corrupt();
+ }
+ return delegate.read(b);
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (corruptRead) {
+ corrupt();
+ }
+ return delegate.read(b, off, len);
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ if (corruptRead) {
+ corrupt();
+ }
+ return delegate.skip(n);
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (corruptRead) {
+ corrupt();
+ }
+ return delegate.available();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return delegate.markSupported();
+ }
+
+ @Override
+ public void mark(final int readAheadLimit) {
+ delegate.mark(readAheadLimit);
+ }
+
+ @Override
+ public void reset() {
+ closeCounter.set(0);
+ delegate.reset();
+ }
+
+ @Override
+ public void close() throws IOException {
+ closeCounter.incrementAndGet();
+ if (corruptClose) {
+ corrupt();
+ }
+ delegate.close();
+ }
+
+ public void setCorruptRead(final boolean corruptRead) {
+ this.corruptRead = corruptRead;
+ }
+
+ public void setCorruptClose(final boolean corruptClose) {
+ this.corruptClose = corruptClose;
+ }
+
+ public int getCloseCount() {
+ return closeCounter.get();
+ }
+
+ private static void corrupt() throws IOException {
+ throw new IOException("Apocalypse Now");
+ }
+ }
+
+ @Path("response")
+ public static class Resource {
+
+ public static final String ENTITY = "ENtiTy";
+
+ @GET
+ @Path("corrupted")
+ public CorruptableInputStream corrupted() {
+ return new CorruptableInputStream();
+ }
+
+ @GET
+ @Path("string")
+ public String string() {
+ return ENTITY;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(Resource.class)
+ .registerInstances(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ @Test
+ public void testBufferEntityReadsOriginalStreamTest() throws Exception {
+ final WebTarget target = target("response/corrupted");
+ final CorruptableInputStream cis = new CorruptableInputStream();
+ target.register(new ClientResponseFilter() {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) {
+ responseContext.setEntityStream(cis);
+ }
+
+ });
+ final Response response = target.request().buildGet().invoke();
+
+ try {
+ cis.setCorruptRead(true);
+ response.bufferEntity();
+ fail("ProcessingException expected.");
+ } catch (ProcessingException pe) {
+ // expected
+ assertThat(pe.getCause(), instanceOf(IOException.class));
+ }
+ }
+
+ @Test
+ // See JERSEY-1340
+ public void testSecondUnbufferedRead() throws Exception {
+ final Response response = target("response/string").request(MediaType.TEXT_PLAIN).get();
+ String entity = response.readEntity(String.class);
+ assertEquals(Resource.ENTITY, entity);
+
+ try {
+ response.readEntity(Reader.class);
+ fail("IllegalStateException expected to be thrown.");
+ } catch (IllegalStateException expected) {
+ // passed.
+ }
+ }
+
+ @Test
+ // See JERSEY-1339
+ public void testSecondBufferedRead() throws Exception {
+ final Response response = target("response/string").request(MediaType.TEXT_PLAIN).get();
+ response.bufferEntity();
+
+ String entity;
+
+ entity = response.readEntity(String.class);
+ assertEquals(Resource.ENTITY, entity);
+
+ entity = response.readEntity(String.class);
+ assertEquals(Resource.ENTITY, entity);
+
+ BufferedReader buffered = new BufferedReader(response.readEntity(Reader.class));
+ String line = buffered.readLine();
+ assertEquals(Resource.ENTITY, line);
+
+ byte[] buffer = new byte[0];
+ buffer = response.readEntity(buffer.getClass());
+ String entityFromBytes = new String(buffer);
+ assertEquals(Resource.ENTITY, entityFromBytes);
+ }
+
+ /**
+ * This method tests behavior of input stream operations in case the underlying input stream throws an exception when closed.
+ * Reproducer for JRFCAF-1344.
+ * <p>
+ * UC-1 : Read unbuffered entity and then try to close the context
+ */
+ @Test
+ public void testReadUnbufferedEntityFromStreamThatFailsToClose() throws Exception {
+
+ final CorruptableInputStream entityStream = new CorruptableInputStream();
+ final WebTarget target = target("response/corrupted");
+ target.register(new ClientResponseFilter() {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) {
+ responseContext.setEntityStream(entityStream);
+ }
+
+ });
+ final Response response = target.request().buildGet().invoke();
+ entityStream.setCorruptClose(true);
+
+ // Read entity should not fail - we silently consume the underlying IOException from closed input stream.
+ final String entity = response.readEntity(String.class, null);
+ assertThat("Unexpected response.", entity.toString(), equalTo(Resource.ENTITY));
+ assertEquals("Close not invoked on underlying input stream.", 1, entityStream.getCloseCount());
+
+ // Close should not fail and should be idempotent
+ response.close();
+ response.close();
+ response.close();
+ assertEquals("Close invoked too many times on underlying input stream.", 1, entityStream.getCloseCount());
+
+ try {
+ // UC-1.1 : Try to read an unbuffered entity from a closed context
+ response.readEntity(String.class, null);
+ fail("IllegalStateException expected when reading from a closed context.");
+ // UC-1.1 : END
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ }
+
+ /**
+ * This method tests behavior of input stream operations in case the underlying input stream throws an exception when closed.
+ * Reproducer for JRFCAF-1344.
+ * <p>
+ * UC-2 : Read buffered entity multiple times and then try to close the context
+ */
+ @Test
+ public void testReadBufferedEntityMultipleTimesFromStreamThatFailsToClose() throws Exception {
+ final CorruptableInputStream entityStream = new CorruptableInputStream();
+ final WebTarget target = target("response/corrupted");
+ target.register(new ClientResponseFilter() {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) {
+ responseContext.setEntityStream(entityStream);
+ }
+
+ });
+ final Response response = target.request().buildGet().invoke();
+ entityStream.setCorruptClose(true);
+
+ response.bufferEntity();
+ assertEquals("Close not invoked on underlying input stream.", 1, entityStream.getCloseCount());
+
+ String entity;
+ entity = response.readEntity(String.class, null);
+ assertThat("Unexpected response.", entity.toString(), equalTo(Resource.ENTITY));
+ entity = response.readEntity(String.class, null);
+ assertThat("Unexpected response.", entity.toString(), equalTo(Resource.ENTITY));
+
+ // Close should not fail and should be idempotent
+ response.close();
+ response.close();
+ response.close();
+ assertEquals("Close invoked too many times on underlying input stream.", 1, entityStream.getCloseCount());
+
+ try {
+ // UC-2.1 : Try to read a buffered entity from a closed context
+ response.readEntity(String.class, null);
+ fail("IllegalStateException expected when reading from a closed buffered context.");
+ // UC-2.1 : END
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ // UC-2 : END
+
+ entityStream.reset();
+
+ }
+
+ /**
+ * This method tests behavior of input stream operations in case the underlying input stream throws an exception when closed.
+ * Reproducer for JRFCAF-1344.
+ * <p>
+ * UC-3 : Try to close the response - underlying exception should be reported.
+ */
+ @Test
+ public void testCloseUnreadResponseWithEntityStreamThatFailsToClose() throws Exception {
+ final CorruptableInputStream entityStream = new CorruptableInputStream();
+ final WebTarget target = target("response/corrupted");
+ target.register(new ClientResponseFilter() {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) {
+ responseContext.setEntityStream(entityStream);
+ }
+
+ });
+ final Response response = target.request().buildGet().invoke();
+ entityStream.setCorruptClose(true);
+
+ try {
+ response.close();
+ fail("ProcessingException expected when closing the context and underlying stream throws an IOException.");
+ } catch (ProcessingException pe) {
+ assertThat(pe.getCause(), instanceOf(IOException.class));
+ }
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ShutdownHookMemoryLeakTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ShutdownHookMemoryLeakTest.java
new file mode 100644
index 0000000..eff4b5d
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ShutdownHookMemoryLeakTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientLifecycleListener;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Ensure Jersey connectors do not leak resources
+ * in case multiple client runtime instances are being created.
+ *
+ * On my laptop, 1000 iterations was sufficient to cause
+ * a memory leak until JERSEY-2688 got fixed.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ShutdownHookMemoryLeakTest extends JerseyTest {
+
+ private static final String PATH = "test";
+ private static final int ITERATIONS = 1000;
+
+ private final ConnectorProvider connectorProvider;
+
+ public ShutdownHookMemoryLeakTest(final ConnectorProvider cp) {
+ connectorProvider = cp;
+ }
+
+
+ @Parameterized.Parameters
+ public static List<ConnectorProvider[]> connectionProviders() {
+ return Arrays.asList(new ConnectorProvider[][] {
+ {new GrizzlyConnectorProvider()},
+ {new JettyConnectorProvider()},
+ {new ApacheConnectorProvider()},
+ {new HttpUrlConnectorProvider()}
+ });
+ }
+
+ @Path(PATH)
+ public static class TestResource {
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(connectorProvider);
+ }
+
+ @Test
+ @Ignore("Unstable, ignored for now")
+ public void testClientDoesNotLeakResources() throws Exception {
+
+ final AtomicInteger listenersInitialized = new AtomicInteger(0);
+ final AtomicInteger listenersClosed = new AtomicInteger(0);
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ final Response response = target(PATH).property("another", "runtime").register(new ClientLifecycleListener() {
+ @Override
+ public void onInit() {
+ listenersInitialized.incrementAndGet();
+ }
+
+ @Override
+ public void onClose() {
+ listenersClosed.incrementAndGet();
+ }
+ }).register(LoggingFeature.class).request().get();
+ assertEquals("GET", response.readEntity(String.class));
+ }
+
+ Collection shutdownHooks = getShutdownHooks(client());
+
+ assertThat(String.format(
+ "%s: number of initialized listeners should be the same as number of total request count",
+ connectorProvider.getClass()),
+ listenersInitialized.get(), is(ITERATIONS));
+
+// the following check is fragile, as GC could break it easily
+// assertThat(String.format(
+// "%s: number of closed listeners should correspond to the number of missing hooks",
+// connectorProvider.getClass()),
+// listenersClosed.get(), is(ITERATIONS - shutdownHooks.size()));
+
+ client().close(); // clean up the rest
+
+ assertThat(String.format(
+ "%s: number of closed listeners should be the same as the number of total requests made",
+ connectorProvider.getClass()),
+ listenersClosed.get(), is(ITERATIONS));
+ }
+
+ private Collection getShutdownHooks(javax.ws.rs.client.Client client) throws NoSuchFieldException, IllegalAccessException {
+ JerseyClient jerseyClient = (JerseyClient) client;
+ Field shutdownHooksField = JerseyClient.class.getDeclaredField("shutdownHooks");
+ shutdownHooksField.setAccessible(true);
+ return (Collection) shutdownHooksField.get(jerseyClient);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/TimeoutTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/TimeoutTest.java
new file mode 100644
index 0000000..507321f
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/TimeoutTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Martin Matula
+ */
+public class TimeoutTest extends JerseyTest {
+ @Path("/test")
+ public static class TimeoutResource {
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @GET
+ @Path("timeout")
+ public String getTimeout() {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return "GET";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TimeoutResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(ClientProperties.READ_TIMEOUT, 2000);
+ }
+
+ @Test
+ public void testFast() {
+ Response r = target("test").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("GET", r.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlow() {
+ try {
+ target("test/timeout").request().get();
+ fail("Timeout expected.");
+ } catch (ProcessingException e) {
+ if (!(e.getCause() instanceof IOException)) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java
new file mode 100644
index 0000000..3886ef1
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.PATCH;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class HttpPatchTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(RequestHeaderModificationsTest.class.getName());
+
+ @Parameterized.Parameters(name = "{index}: {0}")
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][]{
+ // {HttpUrlConnectorProvider.class}, // cannot process PATCH without additional configuration
+ {GrizzlyConnectorProvider.class},
+ {JettyConnectorProvider.class}, // unstable.
+ {ApacheConnectorProvider.class},
+ {GrizzlyConnectorProvider.class},
+ {NettyConnectorProvider.class},
+ {JdkConnectorProvider.class},
+ });
+ }
+
+ private final ConnectorProvider connectorProvider;
+
+ public HttpPatchTest(Class<? extends ConnectorProvider> connectorProviderClass)
+ throws IllegalAccessException, InstantiationException {
+ this.connectorProvider = connectorProviderClass.newInstance();
+ }
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(PatchResource.class)
+ .register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.HEADERS_ONLY));
+ }
+
+ @Override
+ protected void configureClient(ClientConfig clientConfig) {
+ clientConfig.connectorProvider(connectorProvider);
+ }
+
+ @Test
+ public void testPatchResponse() throws Exception {
+ Response response = target().request().method("PATCH", Entity.text("patch"));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("patch", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPatchEntity() throws Exception {
+ String response = target().request().method("PATCH", Entity.text("patch"), String.class);
+
+ assertEquals("patch", response);
+ }
+
+ @Test
+ public void testPatchGenericType() throws Exception {
+ String response = target().request().method("PATCH", Entity.text("patch"), new GenericType<String>() {
+ });
+
+ assertEquals("patch", response);
+ }
+
+ @Test
+ public void testAsyncPatchResponse() throws Exception {
+ Future<Response> response = target().request().async().method("PATCH", Entity.text("patch"));
+
+ assertEquals(200, response.get().getStatus());
+ assertEquals("patch", response.get().readEntity(String.class));
+ }
+
+ @Test
+ public void testAsyncPatchEntity() throws Exception {
+ Future<String> response = target().request().async().method("PATCH", Entity.text("patch"), String.class);
+
+ assertEquals("patch", response.get());
+ }
+
+ @Test
+ public void testAsyncPatchGenericType() throws Exception {
+ Future<String> response = target().request().async().method("PATCH", Entity.text("patch"), new GenericType<String>() {
+ });
+
+ assertEquals("patch", response.get());
+ }
+
+ @Test
+ public void testRxPatchResponse() throws Exception {
+ CompletionStage<Response> response = target().request().rx().method("PATCH", Entity.text("patch"));
+
+ assertEquals(200, response.toCompletableFuture().get().getStatus());
+ assertEquals("patch", response.toCompletableFuture().get().readEntity(String.class));
+ }
+
+ @Test
+ public void testRxPatchEntity() throws Exception {
+ CompletionStage<String> response = target().request().rx().method("PATCH", Entity.text("patch"), String.class);
+
+ assertEquals("patch", response.toCompletableFuture().get());
+ }
+
+ @Test
+ public void testRxPatchGenericType() throws Exception {
+ CompletionStage<String> response = target().request().rx()
+ .method("PATCH", Entity.text("patch"), new GenericType<String>() {
+ });
+
+ assertEquals("patch", response.toCompletableFuture().get());
+ }
+
+ @Path("/")
+ public static class PatchResource {
+
+ @PATCH
+ public String patch(String entity) {
+
+ System.out.println("SERVER: patch request received.");
+
+ return entity;
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java
new file mode 100644
index 0000000..2fab4dc
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JERSEY-2206 reproducer
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class RequestHeaderModificationsTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(RequestHeaderModificationsTest.class.getName());
+ private static final boolean GZIP = false; // change to true when JERSEY-2341 fixed
+ private static final boolean DUMP_ENTITY = false; // I have troubles to dump entity with async jetty!
+
+ private static final String QUESTION = "QUESTION";
+ private static final String ANSWER = "ANSWER";
+ private static final String REQUEST_HEADER_NAME_CLIENT = "Client-Prop";
+ private static final String REQUEST_HEADER_VALUE_CLIENT = "Client-Value";
+ private static final String REQUEST_HEADER_NAME_FILTER = "Filter-Prop";
+ private static final String REQUEST_HEADER_VALUE_FILTER = "Filter-Value";
+ private static final String REQUEST_HEADER_NAME_INTERCEPTOR = "Iceptor-Prop";
+ private static final String REQUEST_HEADER_VALUE_INTERCEPTOR = "Iceptor-Value";
+ private static final String REQUEST_HEADER_NAME_MBW = "Mbw-Prop";
+ private static final String REQUEST_HEADER_VALUE_MBW = "Mbw-Value";
+ private static final String REQUEST_HEADER_MODIFICATION_SUPPORTED = "modificationSupported";
+ private static final String PATH = "/resource";
+
+ @Parameterized.Parameters(name = "{index}: {0} / modificationSupported= {1} / addHeader= {2}")
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {HttpUrlConnectorProvider.class, true, false},
+ {GrizzlyConnectorProvider.class, false, false}, // change to true when JERSEY-2341 fixed
+ {JettyConnectorProvider.class, false, false}, // change to true when JERSEY-2341 fixed
+ {ApacheConnectorProvider.class, false, false}, // change to true when JERSEY-2341 fixed
+ {HttpUrlConnectorProvider.class, true, true},
+ {GrizzlyConnectorProvider.class, false, true}, // change to true when JERSEY-2341 fixed
+ {JettyConnectorProvider.class, false, true}, // change to true when JERSEY-2341 fixed
+ {ApacheConnectorProvider.class, false, true}, // change to true when JERSEY-2341 fixed
+ });
+ }
+
+ private final ConnectorProvider connectorProvider;
+ private final boolean modificationSupported; // remove when JERSEY-2341 fixed
+ private final boolean addHeader;
+
+ public RequestHeaderModificationsTest(Class<? extends ConnectorProvider> connectorProviderClass,
+ boolean modificationSupported, boolean addHeader)
+ throws IllegalAccessException, InstantiationException {
+ this.connectorProvider = connectorProviderClass.newInstance();
+ this.modificationSupported = modificationSupported;
+ this.addHeader = addHeader;
+ }
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+
+ enable(TestProperties.LOG_TRAFFIC);
+ if (DUMP_ENTITY) {
+ enable(TestProperties.DUMP_ENTITY);
+ }
+ return new ResourceConfig(TestResource.class).register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.HEADERS_ONLY));
+ }
+
+ @Override
+ protected void configureClient(ClientConfig clientConfig) {
+ clientConfig.register(MyClientRequestFilter.class);
+ clientConfig.register(new MyWriterInterceptor(addHeader));
+ clientConfig.register(new MyMessageBodyWriter(addHeader));
+ clientConfig.connectorProvider(connectorProvider);
+ }
+
+ @Test
+ public void testWarningLogged() throws Exception {
+ Response response = requestBuilder().post(requestEntity());
+ assertResponse(response);
+ }
+
+ @Test
+ public void testWarningLoggedAsync() throws Exception {
+ AsyncInvoker asyncInvoker = requestBuilder().async();
+ Future<Response> responseFuture = asyncInvoker.post(requestEntity());
+ Response response = responseFuture.get();
+ assertResponse(response);
+ }
+
+ private Invocation.Builder requestBuilder() {
+ return target(PATH)
+ .request()
+ .header(REQUEST_HEADER_NAME_CLIENT, REQUEST_HEADER_VALUE_CLIENT)
+ .header(REQUEST_HEADER_MODIFICATION_SUPPORTED, modificationSupported && addHeader)
+ .header("hello", "double").header("hello", "value");
+ }
+
+ private Entity<MyEntity> requestEntity() {
+ return Entity.text(new MyEntity(QUESTION));
+ }
+
+ private void assertResponse(Response response) {
+ if (!modificationSupported) {
+ final String UNSENT_HEADER_CHANGES = "Unsent header changes";
+ LogRecord logRecord = findLogRecord(UNSENT_HEADER_CHANGES);
+ if (addHeader) {
+ assertNotNull("Missing LogRecord for message '" + UNSENT_HEADER_CHANGES + "'.", logRecord);
+ assertThat(logRecord.getMessage(), containsString(REQUEST_HEADER_NAME_INTERCEPTOR));
+ assertThat(logRecord.getMessage(), containsString(REQUEST_HEADER_NAME_MBW));
+ } else {
+ assertNull("Unexpected LogRecord for message '" + UNSENT_HEADER_CHANGES + "'.", logRecord);
+ }
+ }
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ANSWER, response.readEntity(String.class));
+ }
+
+ private LogRecord findLogRecord(String messageContains) {
+ for (final LogRecord record : getLoggedRecords()) {
+ if (record.getMessage().contains(messageContains)) {
+ return record;
+ }
+ }
+ return null;
+ }
+
+ @Path(PATH)
+ public static class TestResource {
+
+ @POST
+ public String handle(InputStream questionStream,
+ @HeaderParam(REQUEST_HEADER_NAME_CLIENT) String client,
+ @HeaderParam(REQUEST_HEADER_NAME_FILTER) String filter,
+ @HeaderParam(REQUEST_HEADER_NAME_INTERCEPTOR) String interceptor,
+ @HeaderParam(REQUEST_HEADER_NAME_MBW) String mbw,
+ @HeaderParam(REQUEST_HEADER_MODIFICATION_SUPPORTED) boolean modificationSupported)
+ throws IOException {
+ assertEquals(REQUEST_HEADER_VALUE_CLIENT, client);
+ assertEquals(REQUEST_HEADER_VALUE_FILTER, filter);
+ if (modificationSupported) {
+ assertEquals(REQUEST_HEADER_VALUE_INTERCEPTOR, interceptor);
+ assertEquals(REQUEST_HEADER_VALUE_MBW, mbw);
+ }
+ assertEquals(QUESTION, new Scanner(GZIP ? new GZIPInputStream(questionStream) : questionStream).nextLine());
+ return ANSWER;
+ }
+ }
+
+ public static class MyWriterInterceptor implements WriterInterceptor {
+
+ private final boolean addHeader;
+
+ public MyWriterInterceptor(boolean addHeader) {
+ this.addHeader = addHeader;
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ if (addHeader) {
+ context.getHeaders().add(REQUEST_HEADER_NAME_INTERCEPTOR, REQUEST_HEADER_VALUE_INTERCEPTOR);
+ }
+ if (GZIP) {
+ context.setOutputStream(new GZIPOutputStream(context.getOutputStream()));
+ }
+ context.proceed();
+ }
+ }
+
+ public static class MyClientRequestFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().add(REQUEST_HEADER_NAME_FILTER, REQUEST_HEADER_VALUE_FILTER);
+ }
+ }
+
+ @Priority(Priorities.ENTITY_CODER)
+ public static class MyMessageBodyWriter implements MessageBodyWriter<MyEntity> {
+
+ private final boolean addHeader;
+
+ public MyMessageBodyWriter(boolean addHeader) {
+ this.addHeader = addHeader;
+ }
+
+ @Override
+ public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(MyEntity o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1; //ignored
+ }
+
+ @Override
+ public void writeTo(MyEntity o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ if (addHeader) {
+ httpHeaders.add(REQUEST_HEADER_NAME_MBW, REQUEST_HEADER_VALUE_MBW);
+ }
+ entityStream.write(o.getValue().getBytes());
+ }
+ }
+
+ public static class MyEntity {
+
+ private String value;
+
+ public MyEntity() {
+ }
+
+ public MyEntity(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
new file mode 100644
index 0000000..e0315f4
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import javax.net.ssl.SSLContext;
+
+import org.glassfish.jersey.SslConfigurator;
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import com.google.common.io.ByteStreams;
+
+/**
+ * SSL connector hostname verification tests.
+ *
+ * @author Petr Bouda
+ */
+@RunWith(Parameterized.class)
+public abstract class AbstractConnectorServerTest {
+
+ // Default truststore and keystore
+ private static final String CLIENT_TRUST_STORE = "truststore-localhost-client";
+ private static final String SERVER_KEY_STORE = "keystore-localhost-server";
+ private static final String CLIENT_KEY_STORE = "keystore-client";
+
+ /**
+ * Test parameters provider.
+ *
+ * @return test parameters.
+ */
+ @Parameterized.Parameters(name = "{index}: {0}")
+ public static Iterable<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {new HttpUrlConnectorProvider()},
+ {new GrizzlyConnectorProvider()},
+ {new JettyConnectorProvider()},
+ {new ApacheConnectorProvider()}
+ });
+ }
+
+ @Parameterized.Parameter(0)
+ public ConnectorProvider connectorProvider;
+
+ private final Object serverGuard = new Object();
+ private Server server = null;
+
+ @Before
+ public void setUp() throws Exception {
+ synchronized (serverGuard) {
+ if (server != null) {
+ throw new IllegalStateException(
+ "Test run sync issue: Another instance of the SSL-secured HTTP test server has been already started.");
+ }
+ server = Server.start(serverKeyStore());
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ synchronized (serverGuard) {
+ if (server == null) {
+ throw new IllegalStateException("Test run sync issue: There is no SSL-secured HTTP test server to stop.");
+ }
+ server.stop();
+ server = null;
+ }
+ }
+
+ protected SSLContext getSslContext() throws IOException {
+ final InputStream trustStore = SslConnectorConfigurationTest.class.getResourceAsStream(clientTrustStore());
+ final InputStream keyStore = SslConnectorConfigurationTest.class.getResourceAsStream(CLIENT_KEY_STORE);
+ return SslConfigurator.newInstance()
+ .trustStoreBytes(ByteStreams.toByteArray(trustStore))
+ .trustStorePassword("asdfgh")
+ .keyStoreBytes(ByteStreams.toByteArray(keyStore))
+ .keyPassword("asdfgh")
+ .createSSLContext();
+ }
+
+ protected String serverKeyStore() {
+ return SERVER_KEY_STORE;
+ }
+
+ protected String clientTrustStore() {
+ return CLIENT_TRUST_STORE;
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationException.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationException.java
new file mode 100644
index 0000000..f76cf85
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationException.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+/**
+ * A runtime exception representing a failure to provide correct authentication credentials.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class AuthenticationException extends RuntimeException {
+
+ /**
+ * Create new authentication exception.
+ *
+ * @param message error message.
+ * @param realm security realm.
+ */
+ public AuthenticationException(String message, String realm) {
+ super(message);
+ this.realm = realm;
+ }
+
+ private String realm = null;
+
+ /**
+ * Get security realm.
+ *
+ * @return security realm.
+ */
+ public String getRealm() {
+ return this.realm;
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationExceptionMapper.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationExceptionMapper.java
new file mode 100644
index 0000000..53912f8
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AuthenticationExceptionMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Map an authentication exception to an HTTP 401 response,
+ * optionally including the realm for a credentials challenge at the client.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Provider
+public class AuthenticationExceptionMapper implements ExceptionMapper<AuthenticationException> {
+
+ @Override
+ public Response toResponse(AuthenticationException e) {
+ if (e.getRealm() != null) {
+ return Response
+ .status(Status.UNAUTHORIZED)
+ .header("WWW-Authenticate", "Basic realm=\"" + e.getRealm() + "\"")
+ .type("text/plain")
+ .entity(e.getMessage())
+ .build();
+ } else {
+ return Response
+ .status(Status.UNAUTHORIZED)
+ .type("text/plain")
+ .entity(e.getMessage())
+ .build();
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/RootResource.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/RootResource.java
new file mode 100644
index 0000000..bccbf94
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/RootResource.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+
+import org.glassfish.jersey.internal.util.Base64;
+
+/**
+ * Simple resource demonstrating low level approach of getting user credentials.
+ *
+ * A better way would be injecting {@link javax.ws.rs.core.SecurityContext}.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("/")
+public class RootResource {
+ private static final Logger LOGGER = Logger.getLogger(RootResource.class.getName());
+ /**
+ * Served content.
+ */
+ public static final String CONTENT = "JERSEY HTTPS EXAMPLE\n";
+
+ /**
+ * Serve content.
+ *
+ * @param headers request headers.
+ * @return content (see {@link #CONTENT}).
+ */
+ @GET
+ public String getContent(@Context HttpHeaders headers) {
+ // you can get username form HttpHeaders
+ LOGGER.info("Service: GET / User: " + getUser(headers));
+
+ return CONTENT;
+ }
+
+ private String getUser(HttpHeaders headers) {
+ // this is a very minimalistic and "naive" code;
+ // if you plan to use it, add the necessary checks
+ String auth = headers.getRequestHeader("authorization").get(0);
+
+ auth = auth.substring("Basic ".length());
+ String[] values = Base64.decodeAsString(auth).split(":");
+
+ // String username = values[0];
+ // String password = values[1];
+ return values[0];
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SecurityFilter.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SecurityFilter.java
new file mode 100644
index 0000000..128d4cf
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SecurityFilter.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.logging.Logger;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.internal.util.Base64;
+import org.glassfish.jersey.server.ContainerRequest;
+
+/**
+ * Simple authentication filter.
+ *
+ * Returns response with http status 401 when proper authentication is not provided in incoming request.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @see ContainerRequestFilter
+ */
+@Provider
+@PreMatching
+public class SecurityFilter implements ContainerRequestFilter {
+
+ /**
+ * Security realm.
+ */
+ public static final String REALM = "Test HTTPS Authentication REALM";
+ private static final Logger LOGGER = Logger.getLogger(SecurityFilter.class.getName());
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Override
+ public void filter(ContainerRequestContext filterContext) throws IOException {
+ User user = authenticate(filterContext.getRequest());
+ filterContext.setSecurityContext(new AuthorizationContext(user));
+ }
+
+ private User authenticate(Request request) {
+ // Extract authentication credentials
+ String authentication = ((ContainerRequest) request).getHeaderString(HttpHeaders.AUTHORIZATION);
+ if (authentication == null) {
+ throw new AuthenticationException("Authentication credentials are required", REALM);
+ }
+ if (!authentication.startsWith("Basic ")) {
+ return null;
+ // additional checks should be done here
+ // "Only HTTP Basic authentication is supported"
+ }
+ authentication = authentication.substring("Basic ".length());
+ String[] values = Base64.decodeAsString(authentication).split(":");
+ if (values.length < 2) {
+ throw new WebApplicationException(400);
+ // "Invalid syntax for username and password"
+ }
+ String username = values[0];
+ String password = values[1];
+ if ((username == null) || (password == null)) {
+ throw new WebApplicationException(400);
+ // "Missing username or password"
+ }
+
+ // Validate the extracted credentials
+ User user;
+
+ if ("user".equals(username) && "password".equals(password)) {
+ user = new User("user", "user");
+ LOGGER.info("USER AUTHENTICATED");
+ } else {
+ LOGGER.info("USER NOT AUTHENTICATED");
+ throw new AuthenticationException("Invalid username or password", REALM);
+ }
+ return user;
+ }
+
+ private class AuthorizationContext implements SecurityContext {
+
+ private final User user;
+ private final Principal principal;
+
+ public AuthorizationContext(final User user) {
+ this.user = user;
+ this.principal = new Principal() {
+
+ @Override
+ public String getName() {
+ return user.username;
+ }
+ };
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return this.principal;
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ return (role.equals(user.role));
+ }
+
+ @Override
+ public boolean isSecure() {
+ return "https".equals(uriInfo.getRequestUri().getScheme());
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ return SecurityContext.BASIC_AUTH;
+ }
+ }
+
+ private static class User {
+
+ public String username;
+ public String role;
+
+ public User(String username, String role) {
+ this.username = username;
+ this.role = role;
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java
new file mode 100644
index 0000000..ca3cb39
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.ssl.SSLContextConfigurator;
+import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
+
+import com.google.common.io.ByteStreams;
+
+/**
+ * A simple SSL-secured HTTP server for testing purposes.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+final class Server {
+
+ private static final Logger LOGGER = Logger.getLogger(Server.class.getName());
+
+ private static final String SERVER_TRUST_STORE = "truststore-server";
+
+ /**
+ * Base server URI.
+ */
+ public static final URI BASE_URI = getBaseURI();
+
+ private final HttpServer webServer;
+
+ private Server(final HttpServer webServer) {
+ this.webServer = webServer;
+ }
+
+ private static URI getBaseURI() {
+ return UriBuilder.fromUri("https://localhost/").port(getPort(8463)).build();
+ }
+
+ private static int getPort(int defaultPort) {
+ final String port = System.getProperty("jersey.config.test.container.port");
+ if (null != port) {
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ LOGGER.warning("Value of jersey.config.test.container.port property"
+ + " is not a valid positive integer [" + port + "]."
+ + " Reverting to default [" + defaultPort + "].");
+ }
+ }
+ return defaultPort;
+ }
+
+ /**
+ * Start SSL-secured HTTP test server.
+ *
+ * @throws IOException in case there is an error while reading server key store or trust store.
+ * @return an instance of the started SSL-secured HTTP test server.
+ */
+ public static Server start(String keystore) throws IOException {
+ final InputStream trustStore = Server.class.getResourceAsStream(SERVER_TRUST_STORE);
+ final InputStream keyStore = Server.class.getResourceAsStream(keystore);
+
+ // Grizzly ssl configuration
+ SSLContextConfigurator sslContext = new SSLContextConfigurator();
+
+ // set up security context
+ sslContext.setKeyStoreBytes(ByteStreams.toByteArray(keyStore)); // contains server key pair
+ sslContext.setKeyStorePass("asdfgh");
+ sslContext.setTrustStoreBytes(ByteStreams.toByteArray(trustStore)); // contains client certificate
+ sslContext.setTrustStorePass("asdfgh");
+
+ ResourceConfig rc = new ResourceConfig();
+ rc.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ rc.registerClasses(RootResource.class, SecurityFilter.class, AuthenticationExceptionMapper.class);
+
+ final HttpServer grizzlyServer = GrizzlyHttpServerFactory.createHttpServer(
+ getBaseURI(),
+ rc,
+ true,
+ new SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(true)
+ );
+
+ // start Grizzly embedded server //
+ LOGGER.info("Jersey app started. Try out " + BASE_URI + "\nHit CTRL + C to stop it...");
+ grizzlyServer.start();
+
+ return new Server(grizzlyServer);
+ }
+
+ /**
+ * Stop SSL-secured HTTP test server.
+ */
+ public void stop() {
+ webServer.shutdownNow();
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorConfigurationTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorConfigurationTest.java
new file mode 100644
index 0000000..07edcb3
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorConfigurationTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import javax.net.ssl.SSLContext;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * SSL connector tests.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class SslConnectorConfigurationTest extends AbstractConnectorServerTest {
+
+ /**
+ * Test to see that the correct Http status is returned.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testSSLWithAuth() throws Exception {
+ final SSLContext sslContext = getSslContext();
+
+ final ClientConfig cc = new ClientConfig().connectorProvider(connectorProvider);
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(cc)
+ .sslContext(sslContext)
+ .build();
+
+ // client basic auth demonstration
+ client.register(HttpAuthenticationFeature.basic("user", "password"));
+ final WebTarget target = client.target(Server.BASE_URI).register(LoggingFeature.class);
+
+ final Response response = target.path("/").request().get(Response.class);
+
+ assertEquals(200, response.getStatus());
+ }
+
+ /**
+ * Test to see that HTTP 401 is returned when client tries to GET without
+ * proper credentials.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testHTTPBasicAuth1() throws Exception {
+ final SSLContext sslContext = getSslContext();
+
+ final ClientConfig cc = new ClientConfig().connectorProvider(new ApacheConnectorProvider());
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(cc)
+ .sslContext(sslContext)
+ .build();
+
+ final WebTarget target = client.target(Server.BASE_URI).register(LoggingFeature.class);
+
+ final Response response = target.path("/").request().get(Response.class);
+
+ assertEquals(401, response.getStatus());
+ }
+
+ /**
+ * Test to see that SSLHandshakeException is thrown when client don't have
+ * trusted key.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testSSLAuth1() throws Exception {
+ final SSLContext sslContext = getSslContext();
+
+ final ClientConfig cc = new ClientConfig().connectorProvider(new ApacheConnectorProvider());
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(cc)
+ .sslContext(sslContext)
+ .build();
+
+ WebTarget target = client.target(Server.BASE_URI).register(LoggingFeature.class);
+
+ boolean caught = false;
+ try {
+ target.path("/").request().get(String.class);
+ } catch (Exception e) {
+ caught = true;
+ }
+
+ assertTrue(caught);
+ }
+
+ /**
+ * Test that a response to an authentication challenge has the same SSL configuration as the original request.
+ */
+ @Test
+ public void testSSLWithNonPreemptiveAuth() throws Exception {
+ final SSLContext sslContext = getSslContext();
+
+ final ClientConfig cc = new ClientConfig().connectorProvider(connectorProvider);
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(cc)
+ .sslContext(sslContext)
+ .build();
+
+ // client basic auth demonstration
+ HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basicBuilder()
+ .nonPreemptive()
+ .credentials("user", "password")
+ .build();
+
+ client.register(authFeature);
+ final WebTarget target = client.target(Server.BASE_URI).register(LoggingFeature.class);
+
+ final Response response = target.path("/").request().get(Response.class);
+
+ assertEquals(200, response.getStatus());
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java
new file mode 100644
index 0000000..a41f218
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Response;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * SSL connector hostname verification tests.
+ *
+ * @author Petr Bouda
+ */
+@RunWith(Parameterized.class)
+public class SslConnectorHostnameVerifierTest extends AbstractConnectorServerTest {
+
+ private static final String CLIENT_TRUST_STORE = "truststore-example_com-client";
+ private static final String SERVER_KEY_STORE = "keystore-example_com-server";
+
+ @Override
+ protected String serverKeyStore() {
+ return SERVER_KEY_STORE;
+ }
+
+ @Override
+ protected String clientTrustStore() {
+ return CLIENT_TRUST_STORE;
+ }
+
+ /**
+ * Test to apply {@link HostnameVerifier} along with SSL in the predefined connectors
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testHostnameVerifierApplied() throws Exception {
+ // Grizzly and Jetty connectors don't support Hostname Verification
+ if (isExcluded(Arrays.asList(GrizzlyConnectorProvider.class, JettyConnectorProvider.class))) {
+ return;
+ }
+
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(new ClientConfig().connectorProvider(connectorProvider))
+ .register(HttpAuthenticationFeature.basic("user", "password"))
+ .hostnameVerifier(new CustomHostnameVerifier())
+ .sslContext(getSslContext())
+ .build();
+
+ try {
+ client.target(Server.BASE_URI).request().get(Response.class);
+ fail("HostnameVerifier was not applied.");
+ } catch (ProcessingException pex) {
+ CustomHostnameVerifier.HostnameVerifierException hve = getHVE(pex);
+
+ if (hve != null) {
+ assertEquals(CustomHostnameVerifier.EX_VERIFIER_MESSAGE, hve.getMessage());
+ } else {
+ fail("Invalid wrapped exception.");
+ }
+ }
+ }
+
+ private boolean isExcluded(List<Class<? extends ConnectorProvider>> excluded) {
+ for (Class<?> clazz : excluded) {
+ if (clazz.isAssignableFrom(connectorProvider.getClass())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static CustomHostnameVerifier.HostnameVerifierException getHVE(final Throwable stacktrace) {
+ Throwable temp = stacktrace;
+ do {
+ temp = temp.getCause();
+ if (temp instanceof CustomHostnameVerifier.HostnameVerifierException) {
+ return (CustomHostnameVerifier.HostnameVerifierException) temp;
+ }
+ } while (temp != null);
+ return null;
+ }
+
+ public static class CustomHostnameVerifier implements HostnameVerifier {
+
+ private static final String EX_VERIFIER_MESSAGE = "Verifier Applied";
+
+ @Override
+ public boolean verify(final String s, final SSLSession sslSession) {
+ throw new HostnameVerifierException(EX_VERIFIER_MESSAGE);
+ }
+
+ @Override
+ public final String toString() {
+ return "CUSTOM_HOST_VERIFIER";
+ }
+
+ public static class HostnameVerifierException extends RuntimeException {
+
+ public HostnameVerifierException(final String message) {
+ super(message);
+ }
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java
new file mode 100644
index 0000000..7a82321
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector.ssl;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Response;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test custom socket factory in HttpUrlConnection using SSL
+ *
+ * @author Petr Bouda
+ */
+public class SslHttpUrlConnectorTest extends AbstractConnectorServerTest {
+
+ /**
+ * Test to see that the correct Http status is returned.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testSSLWithCustomSocketFactory() throws Exception {
+ final SSLContext sslContext = getSslContext();
+ final CustomSSLSocketFactory socketFactory = new CustomSSLSocketFactory(sslContext);
+
+ final ClientConfig cc = new ClientConfig()
+ .connectorProvider(new HttpUrlConnectorProvider().connectionFactory(
+ new HttpUrlConnectorProvider.ConnectionFactory() {
+ @Override
+ public HttpURLConnection getConnection(final URL url) throws IOException {
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ connection.setSSLSocketFactory(socketFactory);
+ return connection;
+ }
+ }));
+
+ final Client client = ClientBuilder.newBuilder()
+ .withConfig(cc)
+ .sslContext(sslContext)
+ .register(HttpAuthenticationFeature.basic("user", "password"))
+ .register(LoggingFeature.class)
+ .build();
+
+ final Response response = client.target(Server.BASE_URI).path("/").request().get();
+ assertEquals(200, response.getStatus());
+ assertTrue(socketFactory.isVisited());
+ }
+
+ public static class CustomSSLSocketFactory extends SSLSocketFactory {
+
+ private boolean visited = false;
+
+ private final SSLContext sslContext;
+
+ protected CustomSSLSocketFactory(SSLContext sslContext) {
+ this.sslContext = sslContext;
+ }
+
+ public boolean isVisited() {
+ return visited;
+ }
+
+ @Override
+ public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
+ this.visited = true;
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+ return sslSocketFactory.createSocket(s, host, port, autoClose);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ throw new UnsupportedOperationException("This createSocket method should not be invoked.");
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
+ throw new UnsupportedOperationException("This createSocket method should not be invoked.");
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ throw new UnsupportedOperationException("This createSocket method should not be invoked.");
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException {
+ throw new UnsupportedOperationException("This createSocket method should not be invoked.");
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return null;
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return null;
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/grizzlyconnector/NonBlockingTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/grizzlyconnector/NonBlockingTest.java
new file mode 100644
index 0000000..5006b19
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/grizzlyconnector/NonBlockingTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.grizzlyconnector;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Grizzly connector non blocking test.
+ */
+public class NonBlockingTest extends JerseyTest {
+
+ @Path("/test")
+ public static class Resource {
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(new GrizzlyConnectorProvider());
+ }
+
+ private volatile String invocationCallbackThreadName;
+
+ @Test
+ public void testNonBlockingConnector() throws Exception {
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ Future<String> future = target("test")
+ .request()
+ .async()
+ .get(new InvocationCallback<String>() {
+ @Override
+ public void completed(String response) {
+ invocationCallbackThreadName = Thread.currentThread().getName();
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void failed(Throwable throwable) {
+ invocationCallbackThreadName = Thread.currentThread().getName();
+ countDownLatch.countDown();
+ }
+ });
+
+ String response = future.get();
+ assertNotNull(response);
+ assertTrue("Invocation callback was not invoked",
+ countDownLatch.await(5, TimeUnit.SECONDS));
+ assertTrue("Invocation callback is not executed on the NIO pool thread.",
+ !invocationCallbackThreadName.contains("jersey-client-async-executor"));
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/AsyncTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/AsyncTest.java
new file mode 100644
index 0000000..202fe32
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/AsyncTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.httpurlconnector;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.container.TimeoutHandler;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.hamcrest.Matchers;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Asynchronous connector test.
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class AsyncTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(AsyncTest.class.getName());
+ private static final String PATH = "async";
+
+ /**
+ * Asynchronous test resource.
+ */
+ @Path(PATH)
+ public static class AsyncResource {
+ /**
+ * Typical long-running operation duration.
+ */
+ public static final long OPERATION_DURATION = 1000;
+
+ /**
+ * Long-running asynchronous post.
+ *
+ * @param asyncResponse async response.
+ * @param id post request id (received as request payload).
+ */
+ @POST
+ public void asyncPost(@Suspended final AsyncResponse asyncResponse, final String id) {
+ LOGGER.info("Long running post operation called with id " + id + " on thread " + Thread.currentThread().getName());
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ final String result = veryExpensiveOperation();
+ asyncResponse.resume(result);
+ }
+
+ private String veryExpensiveOperation() {
+ // ... very expensive operation that typically finishes within 1 seconds, simulated using sleep()
+ try {
+ Thread.sleep(OPERATION_DURATION);
+ return "DONE-" + id;
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return "INTERRUPTED-" + id;
+ } finally {
+ LOGGER.info("Long running post operation finished on thread " + Thread.currentThread().getName());
+ }
+ }
+ }, "async-post-runner-" + id).start();
+ }
+
+ /**
+ * Long-running async get request that times out.
+ *
+ * @param asyncResponse async response.
+ */
+ @GET
+ @Path("timeout")
+ public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) {
+ LOGGER.info("Async long-running get with timeout called on thread " + Thread.currentThread().getName());
+ asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+ @Override
+ public void handleTimeout(final AsyncResponse asyncResponse) {
+ asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+ .entity("Operation time out.").build());
+ }
+ });
+ asyncResponse.setTimeout(1, TimeUnit.SECONDS);
+
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ final String result = veryExpensiveOperation();
+ asyncResponse.resume(result);
+ }
+
+ private String veryExpensiveOperation() {
+ // very expensive operation that typically finishes within 1 second but can take up to 5 seconds,
+ // simulated using sleep()
+ try {
+ Thread.sleep(5 * OPERATION_DURATION);
+ return "DONE";
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return "INTERRUPTED";
+ } finally {
+ LOGGER.info("Async long-running get with timeout finished on thread " + Thread.currentThread().getName());
+ }
+ }
+ }).start();
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(AsyncResource.class, ThreadPoolResource.class)
+ .register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ config.connectorProvider(new HttpUrlConnectorProvider());
+ }
+
+ /**
+ * Test asynchronous POST.
+ *
+ * Send 3 async POST requests and wait to receive the responses. Check the response content and
+ * assert that the operation did not take more than twice as long as a single long operation duration
+ * (this ensures async request execution).
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testAsyncPost() throws Exception {
+ final long tic = System.currentTimeMillis();
+
+ // Submit requests asynchronously.
+ final Future<Response> rf1 = target(PATH).request().async().post(Entity.text("1"));
+ final Future<Response> rf2 = target(PATH).request().async().post(Entity.text("2"));
+ final Future<Response> rf3 = target(PATH).request().async().post(Entity.text("3"));
+ // get() waits for the response
+ final String r1 = rf1.get().readEntity(String.class);
+ final String r2 = rf2.get().readEntity(String.class);
+ final String r3 = rf3.get().readEntity(String.class);
+
+ final long toc = System.currentTimeMillis();
+
+ assertEquals("DONE-1", r1);
+ assertEquals("DONE-2", r2);
+ assertEquals("DONE-3", r3);
+
+ assertThat("Async processing took too long.", toc - tic, Matchers.lessThan(3 * AsyncResource.OPERATION_DURATION));
+ }
+
+ /**
+ * Test accessing an operation that times out on the server.
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testAsyncGetWithTimeout() throws Exception {
+ final Future<Response> responseFuture = target(PATH).path("timeout").request().async().get();
+ // Request is being processed asynchronously.
+ final Response response = responseFuture.get();
+
+ // get() waits for the response
+ assertEquals(503, response.getStatus());
+ assertEquals("Operation time out.", response.readEntity(String.class));
+ }
+
+ @Path("/threadpool")
+ public static class ThreadPoolResource {
+
+ @GET
+ public String get() {
+ sleep();
+ return "GET";
+ }
+
+ private void sleep() {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ex) {
+ // NOOP.
+ }
+ }
+ }
+
+ @Test
+ @Ignore("Unstable test.")
+ public void testClientThreadPool() throws Exception {
+ final AsyncInvoker invoker = ClientBuilder
+ .newClient(new ClientConfig().property(ClientProperties.ASYNC_THREADPOOL_SIZE, 9))
+ .target(getBaseUri())
+ .path("threadpool")
+ .request()
+ .async();
+
+ final CountDownLatch latch = new CountDownLatch(100);
+ final int threadCount = Thread.activeCount();
+
+ final List<Thread> threads = new ArrayList<Thread>(20);
+ for (int i = 0; i < 20; i++) {
+ threads.add(new Thread(new Runnable() {
+ @Override
+ public void run() throws RuntimeException {
+ for (int i = 0; i < 5; i++) {
+ try {
+ assertThat(invoker.get().get().readEntity(String.class), equalTo("GET"));
+ assertThat(Thread.activeCount() - threadCount - 20, lessThanOrEqualTo(10));
+ latch.countDown();
+ } catch (final InterruptedException e) {
+ fail();
+ } catch (final ExecutionException e) {
+ fail();
+ }
+ }
+ }
+ }));
+ }
+ for (final Thread thread : threads) {
+ thread.start();
+ }
+
+ assertTrue(latch.await(10 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS));
+ }
+}
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-client b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-client
new file mode 100644
index 0000000..d016fd2
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-client
Binary files differ
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-example_com-server b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-example_com-server
new file mode 100644
index 0000000..66f6e9a
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-example_com-server
Binary files differ
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-localhost-server b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-localhost-server
new file mode 100644
index 0000000..b86a87d
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/keystore-localhost-server
Binary files differ
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-example_com-client b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-example_com-client
new file mode 100644
index 0000000..0cfac86
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-example_com-client
Binary files differ
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-localhost-client b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-localhost-client
new file mode 100644
index 0000000..29d6102
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-localhost-client
Binary files differ
diff --git a/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-server b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-server
new file mode 100644
index 0000000..9b26ce4
--- /dev/null
+++ b/tests/e2e-client/src/test/resources/org/glassfish/jersey/tests/e2e/client/connector/ssl/truststore-server
Binary files differ
diff --git a/tests/e2e-core-common/pom.xml b/tests/e2e-core-common/pom.xml
new file mode 100644
index 0000000..ea70000
--- /dev/null
+++ b/tests/e2e-core-common/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-core-common</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-core-common</name>
+
+ <description>Jersey E2E Core-Common tests</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
new file mode 100644
index 0000000..185202c
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.Variant;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.internal.AbstractRuntimeDelegate;
+import org.glassfish.jersey.message.internal.MessagingBinders;
+
+import org.junit.Assert;
+
+/**
+ * Test runtime delegate.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestRuntimeDelegate extends AbstractRuntimeDelegate {
+
+ public TestRuntimeDelegate() {
+ super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
+ }
+
+ @Override
+ public <T> T createEndpoint(Application application, Class<T> endpointType)
+ throws IllegalArgumentException, UnsupportedOperationException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void testMediaType() {
+ MediaType m = new MediaType("text", "plain");
+ Assert.assertNotNull(m);
+ }
+
+ public void testUriBuilder() {
+ UriBuilder ub = RuntimeDelegate.getInstance().createUriBuilder();
+ Assert.assertNotNull(ub);
+ }
+
+ public void testResponseBuilder() {
+ Response.ResponseBuilder rb = RuntimeDelegate.getInstance().createResponseBuilder();
+ Assert.assertNotNull(rb);
+ }
+
+ public void testVariantListBuilder() {
+ Variant.VariantListBuilder vlb = RuntimeDelegate.getInstance().createVariantListBuilder();
+ Assert.assertNotNull(vlb);
+ }
+
+ public void testLinkBuilder() {
+ final Link.Builder linkBuilder = RuntimeDelegate.getInstance().createLinkBuilder();
+ Assert.assertNotNull(linkBuilder);
+ }
+
+ public void testWebApplicationException() {
+ WebApplicationException wae = new WebApplicationException();
+ Assert.assertNotNull(wae);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/ServiceFinderBinderTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/ServiceFinderBinderTest.java
new file mode 100644
index 0000000..1195233
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/ServiceFinderBinderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.internal.ServiceFinderBinder;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.Providers;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Service finder injection binder unit test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ServiceFinderBinderTest {
+
+ private static InjectionManager injectionManager;
+
+ public ServiceFinderBinderTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ AbstractBinder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(TestServiceB.class).to(TestContract.class);
+ bind(TestServiceD.class).to(TestContract.class);
+ install(new ServiceFinderBinder<>(TestContract.class, null, RuntimeType.SERVER));
+ }
+ };
+ injectionManager = Injections.createInjectionManager(binder);
+ injectionManager.completeRegistration();
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Test
+ public void testConfigure() {
+ final Set<TestContract> providers = Providers.getProviders(injectionManager, TestContract.class);
+ assertEquals(4, providers.size());
+
+ final Collection<String> providerNames =
+ providers.stream()
+ .map(TestContract::name)
+ .collect(Collectors.toList());
+
+ assertTrue(providerNames.contains(TestServiceA.class.getName()));
+ assertTrue(providerNames.contains(TestServiceB.class.getName()));
+ assertTrue(providerNames.contains(TestServiceC.class.getName()));
+ assertTrue(providerNames.contains(TestServiceD.class.getName()));
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestContract.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestContract.java
new file mode 100644
index 0000000..3aa1482
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestContract.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+/**
+ * Test contract for {@link org.glassfish.jersey.internal.ServiceFinderBinder} test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public interface TestContract {
+ /**
+ * Get service name.
+ *
+ * @return service name.
+ */
+ public String name();
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceA.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceA.java
new file mode 100644
index 0000000..046d639
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceA.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+/**
+ * Test contract implementation.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestServiceA implements TestContract {
+
+ @Override
+ public String name() {
+ return getClass().getName();
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceB.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceB.java
new file mode 100644
index 0000000..cd957b9
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceB.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+/**
+ * Test contract implementation.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestServiceB implements TestContract {
+
+ @Override
+ public String name() {
+ return getClass().getName();
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceC.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceC.java
new file mode 100644
index 0000000..6409a38
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceC.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+/**
+ * Test contract implementation.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestServiceC implements TestContract {
+
+ @Override
+ public String name() {
+ return getClass().getName();
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceD.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceD.java
new file mode 100644
index 0000000..8a73c53
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/config/TestServiceD.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.config;
+
+/**
+ * Test contract implementation.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestServiceD implements TestContract {
+
+ @Override
+ public String name() {
+ return getClass().getName();
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java
new file mode 100644
index 0000000..7c00edd
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import java.util.Collections;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.internal.ContextResolverFactory;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.ProviderBinder;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Context resolvers factory unit test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ContextResolverFactoryTest {
+
+ @Provider
+ private static class CustomStringResolver implements ContextResolver<String> {
+
+ public static final String VALUE = "foof";
+
+ @Override
+ public String getContext(Class<?> type) {
+ return VALUE;
+ }
+ }
+
+ @Provider
+ @Produces("application/*")
+ private static class CustomIntegerResolverA implements ContextResolver<Integer> {
+
+ public static final int VALUE = 1001;
+
+ @Override
+ public Integer getContext(Class<?> type) {
+ return VALUE;
+ }
+ }
+
+ @Provider
+ @Produces("application/json")
+ private static class CustomIntegerResolverB implements ContextResolver<Integer> {
+
+ public static final int VALUE = 2002;
+
+ @Override
+ public Integer getContext(Class<?> type) {
+ return VALUE;
+ }
+ }
+
+ @Provider
+ @Produces("application/json")
+ private static class CustomIntegerResolverC implements ContextResolver<Integer> {
+
+ public static final int VALUE = 3003;
+
+ @Override
+ public Integer getContext(Class<?> type) {
+ return VALUE;
+ }
+ }
+
+ private static class Binder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(CustomStringResolver.class).to(ContextResolver.class);
+ bind(CustomIntegerResolverA.class).to(ContextResolver.class);
+ bind(CustomIntegerResolverB.class).to(ContextResolver.class);
+ }
+ }
+
+ private ContextResolverFactory crf;
+
+ public ContextResolverFactoryTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Before
+ public void setUp() {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindClasses(Collections.singleton(CustomIntegerResolverC.class));
+ injectionManager.register(new Binder());
+
+ BootstrapBag bootstrapBag = new BootstrapBag();
+ ContextResolverFactory.ContextResolversConfigurator configurator =
+ new ContextResolverFactory.ContextResolversConfigurator();
+ configurator.init(injectionManager, bootstrapBag);
+ injectionManager.completeRegistration();
+ configurator.postInit(injectionManager, bootstrapBag);
+
+ crf = injectionManager.getInstance(ContextResolverFactory.class);
+ }
+
+ @Test
+ public void testResolve() {
+ assertEquals(CustomStringResolver.VALUE, crf.resolve(String.class, MediaType.WILDCARD_TYPE).getContext(String.class));
+ assertEquals(CustomStringResolver.VALUE, crf.resolve(String.class, MediaType.TEXT_PLAIN_TYPE).getContext(String.class));
+
+ assertEquals(CustomIntegerResolverA.VALUE,
+ crf.resolve(Integer.class, MediaType.APPLICATION_XML_TYPE).getContext(Integer.class));
+ assertEquals(CustomIntegerResolverA.VALUE,
+ crf.resolve(Integer.class, MediaType.valueOf("application/*")).getContext(Integer.class));
+
+ // Test that resolver "B" is shadowed by a custom resolver "C"
+ assertEquals(CustomIntegerResolverC.VALUE,
+ crf.resolve(Integer.class, MediaType.APPLICATION_JSON_TYPE).getContext(Integer.class));
+
+ // Test that there is no matching provider
+ assertNull(crf.resolve(Integer.class, MediaType.TEXT_PLAIN_TYPE));
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ExceptionMapperFactoryTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ExceptionMapperFactoryTest.java
new file mode 100644
index 0000000..24b4ffa
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ExceptionMapperFactoryTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.ExceptionMapperFactory;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.spi.ExtendedExceptionMapper;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test of {@link ExceptionMapperFactory}.
+ */
+public class ExceptionMapperFactoryTest {
+
+ private static class ExtendedExceptionMappers extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(IllegalArgumentExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
+ bind(IllegalStateExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
+ }
+
+ }
+
+ private static class AllMappers extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(IllegalArgumentExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
+ bind(IllegalStateExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
+ bind(RuntimeExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
+ }
+
+ }
+
+ /**
+ * Test spec:
+ * <p/>
+ * setup:<br/>
+ * - have two extended exception mappers, order matters<br/>
+ * - both using the same generic type (RuntimeException)<br/>
+ * - first mapper return isMappable true only to IllegalArgumentException<br/>
+ * - second mapper return isMappable true only to IllegalStateException<br/>
+ * <br/>
+ * when:<br/>
+ * - {@link ExceptionMapperFactory#findMapping(Throwable)} with IllegalArgumentException instance<br/>
+ * <br/>
+ * then:<br/>
+ * - exception mapper factory returns IllegalArgumentExceptionMapper<br/>
+ * <p/>
+ * why:<br/>
+ * - IllegalArgumentException has the same distance (1) for both exception mappers generic type (RuntimeException),
+ * but IllegalArgumentException's isMappable return true, so it is the winner
+ *
+ * @throws Exception unexpected - if anything goes wrong, the test fails
+ */
+ @Test
+ public void testFindMappingExtendedExceptions() throws Exception {
+ final InjectionManager injectionManager = Injections.createInjectionManager(new ExtendedExceptionMappers());
+ injectionManager.completeRegistration();
+ final ExceptionMapperFactory mapperFactory = new ExceptionMapperFactory(injectionManager);
+
+ final ExceptionMapper mapper = mapperFactory.findMapping(new IllegalArgumentException());
+
+ Assert.assertTrue("IllegalArgumentExceptionMapper should be returned",
+ mapper instanceof IllegalArgumentExceptionMapper);
+ }
+
+ /**
+ * Test spec:
+ * <p/>
+ * setup:<br/>
+ * - have 3 exception mappers, order matters<br/>
+ * - first is *not* extended mapper typed to RuntimeException
+ * - second and third are extended mappers type to RuntimeException
+ * <br/>
+ * when:<br/>
+ * - {@link ExceptionMapperFactory#findMapping(Throwable)} invoked with RuntimeException instance<br/>
+ * then: <br/>
+ * - exception mapper factory returns RuntimeExceptionMapper<br/>
+ * <p/>
+ * why:<br/>
+ * - RuntimeException mapper has distance 0 for RuntimeException, it is not extended mapper, so it will be chosen
+ * immediately, cause there is no better option possible
+ *
+ * @throws Exception unexpected - if anything goes wrong, the test fails
+ */
+ @Test
+ public void testFindMapping() throws Exception {
+ final InjectionManager injectionManager = Injections.createInjectionManager(new AllMappers());
+ injectionManager.completeRegistration();
+ final ExceptionMapperFactory mapperFactory = new ExceptionMapperFactory(injectionManager);
+
+ final ExceptionMapper<RuntimeException> mapper = mapperFactory.findMapping(new RuntimeException());
+
+ Assert.assertTrue("RuntimeExceptionMapper should be returned", mapper instanceof RuntimeExceptionMapper);
+ }
+
+ /**
+ * Test spec: <br/>
+ * <p/>
+ * setup:<br/>
+ * - have 2 extended mappers, order matters<br/>
+ * - first mapper return isMappable true only to IllegalArgumentException<br/>
+ * - second mapper return isMappable true only to IllegalStateException<br/>
+ * <br/>
+ * when:<br/>
+ * - {@link ExceptionMapperFactory#find(Class)} invoked with IllegalArgumentException.class<br/>
+ * then:<br/>
+ * - exception mapper factory returns IllegalArgumentExceptionMapper<br/>
+ * <p/>
+ * why:<br/>
+ * - both exception mappers have distance 1 to IllegalArgumentException, we don't have instance of the
+ * IllegalArgumentException, so the isMappable check is not used and both are accepted, the later accepted is
+ * the winner
+ *
+ * @throws Exception unexpected - if anything goes wrong, the test fails
+ */
+ @Test
+ public void testFindExtendedExceptions() throws Exception {
+ final InjectionManager injectionManager = Injections.createInjectionManager(new ExtendedExceptionMappers());
+ injectionManager.completeRegistration();
+ final ExceptionMapperFactory mapperFactory = new ExceptionMapperFactory(injectionManager);
+
+ final ExceptionMapper mapper = mapperFactory.find(IllegalArgumentException.class);
+
+ Assert.assertTrue("IllegalStateExceptionMapper should be returned",
+ mapper instanceof IllegalStateExceptionMapper);
+ }
+
+ /**
+ * Extended Exception Mapper which has RuntimeException as generic type and isMappable returns true if the
+ * exception is instance of IllegalArgumentException.
+ */
+ private static class IllegalArgumentExceptionMapper implements ExtendedExceptionMapper<RuntimeException> {
+
+ @Override
+ public boolean isMappable(final RuntimeException exception) {
+ return exception instanceof IllegalArgumentException;
+ }
+
+ @Override
+ public Response toResponse(final RuntimeException exception) {
+ return Response
+ .status(Response.Status.BAD_REQUEST)
+ .build();
+ }
+
+ }
+
+ /**
+ * Extended Exception Mapper which has RuntimeException as generic type and isMappable returns true if the
+ * exception is instance of IllegalStateException.
+ */
+ private static class IllegalStateExceptionMapper implements ExtendedExceptionMapper<RuntimeException> {
+
+ @Override
+ public boolean isMappable(final RuntimeException exception) {
+ return exception instanceof IllegalStateException;
+ }
+
+ @Override
+ public Response toResponse(final RuntimeException exception) {
+ return Response
+ .status(Response.Status.SERVICE_UNAVAILABLE)
+ .build();
+ }
+
+ }
+
+ /**
+ * Exception Mapper which has RuntimeException as generic type.
+ */
+ private static class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
+
+ @Override
+ public Response toResponse(final RuntimeException exception) {
+ return Response
+ .status(Response.Status.INTERNAL_SERVER_ERROR)
+ .build();
+ }
+
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/JaxrsProvidersTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/JaxrsProvidersTest.java
new file mode 100644
index 0000000..beb6221
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/JaxrsProvidersTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Providers;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.internal.BootstrapConfigurator;
+import org.glassfish.jersey.internal.ContextResolverFactory;
+import org.glassfish.jersey.internal.ExceptionMapperFactory;
+import org.glassfish.jersey.internal.JaxrsProviders;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.message.internal.MessageBodyFactory;
+import org.glassfish.jersey.message.internal.MessagingBinders;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+import org.glassfish.jersey.process.internal.RequestScope;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+/**®
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class JaxrsProvidersTest {
+
+ private static class Binder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(new ContextResolver<String>() {
+ @Override
+ public String getContext(Class<?> type) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }).to(new GenericType<ContextResolver<String>>() {
+ });
+
+ bind(new CommonConfig(RuntimeType.SERVER, ComponentBag.EXCLUDE_EMPTY)).to(Configuration.class);
+ }
+ }
+
+ public JaxrsProvidersTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Test
+ public void testProviders() throws Exception {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ injectionManager.register(new MessagingBinders.MessageBodyProviders(null, RuntimeType.SERVER));
+ injectionManager.register(new Binder());
+
+ BootstrapBag bootstrapBag = new BootstrapBag();
+ List<BootstrapConfigurator> bootstrapConfigurators = Arrays.asList(
+ new RequestScope.RequestScopeConfigurator(),
+ new TestConfigConfigurator(),
+ new ContextResolverFactory.ContextResolversConfigurator(),
+ new MessageBodyFactory.MessageBodyWorkersConfigurator(),
+ new ExceptionMapperFactory.ExceptionMappersConfigurator(),
+ new JaxrsProviders.ProvidersConfigurator());
+ injectionManager.register(new TestBinder());
+
+ TestBinder.initProviders(injectionManager);
+ bootstrapConfigurators.forEach(configurator -> configurator.init(injectionManager, bootstrapBag));
+ injectionManager.completeRegistration();
+ bootstrapConfigurators.forEach(configurator -> configurator.postInit(injectionManager, bootstrapBag));
+
+ RequestScope scope = bootstrapBag.getRequestScope();
+
+ scope.runInScope((Callable<Object>) () -> {
+ Providers instance = injectionManager.getInstance(Providers.class);
+
+ assertNotNull(instance);
+ assertSame(JaxrsProviders.class, instance.getClass());
+
+ assertNotNull(instance.getExceptionMapper(Throwable.class));
+ assertNotNull(instance.getMessageBodyReader(String.class, String.class, new Annotation[0],
+ MediaType.TEXT_PLAIN_TYPE));
+ assertNotNull(instance.getMessageBodyWriter(String.class, String.class, new Annotation[0],
+ MediaType.TEXT_PLAIN_TYPE));
+ assertNotNull(instance.getContextResolver(String.class, MediaType.TEXT_PLAIN_TYPE));
+ return null;
+ });
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/LocalizationMessagesTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/LocalizationMessagesTest.java
new file mode 100644
index 0000000..22c679f
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/LocalizationMessagesTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+
+import org.glassfish.jersey.internal.LocalizationMessages;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests {@link org.glassfish.jersey.internal.LocalizationMessages}.
+ * @author Miroslav Fuksa
+ */
+public class LocalizationMessagesTest {
+
+ @Test
+ public void test() {
+ Assert.assertTrue(LocalizationMessages.COMPONENT_CONTRACTS_EMPTY_OR_NULL("TYPE")
+ .contains("Attempt to register component of type TYPE"));
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ProviderBinderTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ProviderBinderTest.java
new file mode 100644
index 0000000..8e60873
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ProviderBinderTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.CompositeBinder;
+import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.ProviderBinder;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.message.internal.MessagingBinders;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * ServiceProviders unit test.
+ *
+ * @author Santiago Pericas-Geertsen (santiago.pericasgeertsen at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class ProviderBinderTest {
+
+ private static class MyProvider implements MessageBodyReader, MessageBodyWriter {
+
+ @Override
+ public boolean isReadable(Class type, Type genericType, Annotation[] annotations,
+ MediaType mediaType) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Object readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isWriteable(Class type, Type genericType, Annotation[] annotations,
+ MediaType mediaType) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public long getSize(Object t, Class type, Type genericType, Annotation[] annotations,
+ MediaType mediaType) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void writeTo(Object t, Class type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ private static Binder initBinders(Binder... binders) {
+ List<Binder> binderList = Arrays.stream(binders).collect(Collectors.toList());
+ binderList.add(new MessagingBinders.MessageBodyProviders(null, RuntimeType.SERVER));
+ return CompositeBinder.wrap(binderList);
+ }
+
+ public ProviderBinderTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Test
+ public void testServicesNotEmpty() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ injectionManager.completeRegistration();
+ Set<MessageBodyReader> providers = Providers.getProviders(injectionManager, MessageBodyReader.class);
+ assertTrue(providers.size() > 0);
+ }
+
+ @Test
+ public void testServicesMbr() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ injectionManager.completeRegistration();
+ Set<MessageBodyReader> providers = Providers.getProviders(injectionManager, MessageBodyReader.class);
+ assertTrue(providers.size() > 0);
+ }
+
+ @Test
+ public void testServicesMbw() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ injectionManager.completeRegistration();
+ Set<MessageBodyWriter> providers = Providers.getProviders(injectionManager, MessageBodyWriter.class);
+ assertTrue(providers.size() > 0);
+ }
+
+ @Test
+ public void testProvidersMbr() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindClasses(Collections.singleton(MyProvider.class));
+
+ injectionManager.completeRegistration();
+ Set<MessageBodyReader> providers = Providers.getCustomProviders(injectionManager, MessageBodyReader.class);
+ assertEquals(1, instancesOfType(MyProvider.class, providers).size());
+ }
+
+ @Test
+ public void testProvidersMbw() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindClasses(Collections.singleton(MyProvider.class));
+
+ injectionManager.completeRegistration();
+ Set<MessageBodyWriter> providers = Providers.getCustomProviders(injectionManager, MessageBodyWriter.class);
+ final Collection<MyProvider> myProviders = instancesOfType(MyProvider.class, providers);
+ assertEquals(1, myProviders.size());
+ }
+
+ @Test
+ public void testProvidersMbrInstance() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindInstances(Collections.singleton(new MyProvider()));
+
+ injectionManager.completeRegistration();
+ Set<MessageBodyReader> providers = Providers.getCustomProviders(injectionManager, MessageBodyReader.class);
+ assertEquals(1, instancesOfType(MyProvider.class, providers).size());
+ }
+
+ @Test
+ public void testProvidersMbwInstance() {
+ InjectionManager injectionManager = Injections.createInjectionManager(initBinders());
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindInstances(Collections.singleton(new MyProvider()));
+
+ injectionManager.completeRegistration();
+ Set<MessageBodyWriter> providers = Providers.getCustomProviders(injectionManager, MessageBodyWriter.class);
+ assertEquals(instancesOfType(MyProvider.class, providers).size(), 1);
+ }
+
+ private <T> Collection<T> instancesOfType(final Class<T> c, Collection<?> collection) {
+
+ return collection.stream()
+ .filter((java.util.function.Predicate<Object>) o -> o.getClass() == c)
+ .map((java.util.function.Function<Object, T>) c::cast)
+ .collect(Collectors.toList());
+ }
+
+
+ @Test
+ public void testCustomRegistration() {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+
+ ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindClasses(Child.class);
+ providerBinder.bindClasses(NotFilterChild.class);
+ injectionManager.completeRegistration();
+
+ ContainerRequestFilter requestFilter = getRequestFilter(injectionManager);
+ ContainerRequestFilter requestFilter2 = getRequestFilter(injectionManager);
+ assertEquals(requestFilter, requestFilter2);
+
+
+ ContainerResponseFilter responseFilter = getResponseFilter(injectionManager);
+ ContainerResponseFilter responseFilter2 = getResponseFilter(injectionManager);
+ assertTrue(responseFilter == responseFilter2);
+
+ assertTrue(responseFilter == requestFilter);
+
+ // only one filter should be registered
+ Collection<ContainerResponseFilter> filters =
+ Providers.getCustomProviders(injectionManager, ContainerResponseFilter.class);
+ assertEquals(1, filters.size());
+
+ Child child = injectionManager.getInstance(Child.class);
+ Child child2 = injectionManager.getInstance(Child.class);
+
+ assertTrue(child != responseFilter);
+
+ assertTrue(child == child2);
+ }
+
+ private ContainerResponseFilter getResponseFilter(InjectionManager injectionManager) {
+ ContainerResponseFilter responseFilter =
+ injectionManager.getInstance(ContainerResponseFilter.class, CustomAnnotationLiteral.INSTANCE);
+ assertEquals(Child.class, responseFilter.getClass());
+ return responseFilter;
+ }
+
+ private ContainerRequestFilter getRequestFilter(InjectionManager injectionManager) {
+ ContainerRequestFilter requestFilter =
+ injectionManager.getInstance(ContainerRequestFilter.class, CustomAnnotationLiteral.INSTANCE);
+ assertEquals(Child.class, requestFilter.getClass());
+ return requestFilter;
+ }
+
+ interface ParentInterface {
+ }
+
+ interface ChildInterface extends ChildSuperInterface {
+ }
+
+
+ interface SecondChildInterface {
+ }
+
+ interface ChildSuperInterface extends ContainerResponseFilter {
+ }
+
+ @Singleton
+ public static class Parent implements ParentInterface, ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ }
+ }
+
+ @Singleton
+ public static class Child extends Parent implements ChildInterface, SecondChildInterface {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ }
+ }
+
+ private static class NotFilterChild implements ParentInterface {
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestBinder.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestBinder.java
new file mode 100644
index 0000000..b166748
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestBinder.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import java.util.Collections;
+
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.ProviderBinder;
+import org.glassfish.jersey.message.internal.MessagingBinders;
+
+/**
+ * Binder for testing purposes.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class TestBinder extends AbstractBinder {
+
+ public static void initProviders(final InjectionManager injectionManager) {
+ initProviders(injectionManager, Collections.emptySet(), Collections.emptySet());
+ }
+
+ public static void initProviders(final InjectionManager injectionManager,
+ final Iterable<Class<?>> providerClasses,
+ final Iterable<Object> providerInstances) {
+ final ProviderBinder providerBinder = new ProviderBinder(injectionManager);
+ providerBinder.bindClasses(providerClasses);
+ providerBinder.bindInstances(providerInstances);
+ }
+
+ @Override
+ protected void configure() {
+ install(new MessagingBinders.MessageBodyProviders(null, RuntimeType.SERVER));
+
+ bind(new ExceptionMapper<Throwable>() {
+ @Override
+ public Response toResponse(Throwable exception) {
+ if (exception instanceof NumberFormatException) {
+ return Response.ok(-1).build();
+ }
+
+ throw new RuntimeException(exception);
+ }
+ }).to(ExceptionMapper.class);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestConfigConfigurator.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestConfigConfigurator.java
new file mode 100644
index 0000000..6617ca9
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/TestConfigConfigurator.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal;
+
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.internal.BootstrapConfigurator;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+
+/**
+ * Configurator which initializes configuration.
+ *
+ * @author Petr Bouda
+ */
+public class TestConfigConfigurator implements BootstrapConfigurator {
+
+ @Override
+ public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
+ bootstrapBag.setConfiguration(new CommonConfig(RuntimeType.SERVER, ComponentBag.EXCLUDE_EMPTY));
+ }
+
+ @Override
+ public void postInit(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/inject/ReferencingFactoryTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/inject/ReferencingFactoryTest.java
new file mode 100644
index 0000000..6aaf923
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/inject/ReferencingFactoryTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.internal.inject;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.core.GenericType;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.util.collection.Ref;
+
+import org.junit.Test;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Referencing factory test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ReferencingFactoryTest extends AbstractBinder {
+
+ private static class Foo {
+ final int value;
+
+ private Foo(int value) {
+ this.value = value;
+ }
+ }
+
+ private static class ValueInjected {
+
+ @Inject
+ Foo foo;
+ @Inject
+ List<Integer> integers;
+ @Inject
+ List<String> strings;
+ }
+
+ private static class RefInjected {
+
+ @Inject
+ Ref<Foo> foo;
+ @Inject
+ Ref<List<Integer>> integers;
+ @Inject
+ Ref<List<String>> strings;
+ }
+
+ //
+ private Foo expectedFoo = null;
+ private List<Integer> expectedIntegers = null;
+ private List<String> expectedStrings = new LinkedList<String>();
+
+ private static final class FooReferencingFactory extends ReferencingFactory<Foo> {
+ @Inject
+ public FooReferencingFactory(Provider<Ref<Foo>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ private static final class ListOfIntegerReferencingFactory extends ReferencingFactory<List<Integer>> {
+ @Inject
+ public ListOfIntegerReferencingFactory(Provider<Ref<List<Integer>>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ private static final class ListOfStringReferencingFactory extends ReferencingFactory<List<String>> {
+ @Inject
+ public ListOfStringReferencingFactory(Provider<Ref<List<String>>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ @Override
+ protected void configure() {
+ bindFactory(FooReferencingFactory.class).to(Foo.class);
+ bindFactory(ReferencingFactory.referenceFactory()).to(new GenericType<Ref<Foo>>() {}).in(Singleton.class);
+
+ bindFactory(ListOfIntegerReferencingFactory.class).to(new GenericType<List<Integer>>() {});
+ bindFactory(ReferencingFactory.referenceFactory()).to(new GenericType<Ref<List<Integer>>>() {
+ }).in(Singleton.class);
+
+ bindFactory(ListOfStringReferencingFactory.class).to(new GenericType<List<String>>() {});
+ bindFactory(ReferencingFactory.referenceFactory(expectedStrings)).to(new GenericType<Ref<List<String>>>() {
+ }).in(Singleton.class);
+ }
+
+ /**
+ * Referenced binding test.
+ */
+ @Test
+ public void testReferencedBinding() {
+ InjectionManager injectionManager = Injections.createInjectionManager(this);
+ injectionManager.completeRegistration();
+
+ RefInjected refValues = injectionManager.createAndInitialize(RefInjected.class);
+ expectedFoo = new Foo(10);
+ refValues.foo.set(expectedFoo);
+ expectedIntegers = new LinkedList<Integer>();
+ refValues.integers.set(expectedIntegers);
+ expectedStrings = new ArrayList<String>();
+ refValues.strings.set(expectedStrings);
+
+ ValueInjected updatedValues = injectionManager.createAndInitialize(ValueInjected.class);
+ assertSame(expectedFoo, updatedValues.foo);
+ assertSame(expectedIntegers, updatedValues.integers);
+ assertSame(expectedStrings, updatedValues.strings);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeStringRepresentationTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeStringRepresentationTest.java
new file mode 100644
index 0000000..6714257
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeStringRepresentationTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.glassfish.jersey.message.internal.AcceptableMediaType;
+import org.glassfish.jersey.message.internal.MediaTypeProvider;
+import org.glassfish.jersey.message.internal.Quality;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+
+/**
+ * Acceptable media type unit tests.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class AcceptableMediaTypeStringRepresentationTest {
+ @Parameterized.Parameters
+ // expected result, acceptable media type
+ public static List<Object[]> getParameters() {
+ final Map<String, String> emptyParams = new HashMap<String, String>();
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put("myParam", "myValue");
+
+ return Arrays.asList(new Object[][]{
+ {"*/*", new AcceptableMediaType("*", "*")},
+ {"*/*", new AcceptableMediaType("*", "*", Quality.DEFAULT, emptyParams)},
+ {"*/*;q=0.75", new AcceptableMediaType("*", "*", 750, emptyParams)},
+ {"text/html", new AcceptableMediaType("text", "html", Quality.DEFAULT, null)},
+ {"text/html;q=0.5", new AcceptableMediaType("text", "html", 500, emptyParams)},
+ {"image/*;myparam=myValue;q=0.8", new AcceptableMediaType("image", "*", 800, params)},
+ });
+ }
+
+ private final String expectedValue;
+ private final AcceptableMediaType testedType;
+
+ public AcceptableMediaTypeStringRepresentationTest(final String expectedValue,
+ final AcceptableMediaType testedType) {
+ this.expectedValue = expectedValue;
+ this.testedType = testedType;
+ }
+
+ @Test
+ public void testStringRepresentation() {
+ final MediaTypeProvider provider = new MediaTypeProvider();
+ Assert.assertEquals(expectedValue, testedType.toString());
+ provider.fromString(testedType.toString());
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeTest.java
new file mode 100644
index 0000000..198a905
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/AcceptableMediaTypeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.AcceptableMediaType;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Acceptable media type unit tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class AcceptableMediaTypeTest {
+ @Parameterized.Parameters
+ // expected result, media type, acceptable media type
+ public static List<Object[]> testBeds() {
+ return Arrays.asList(new Object[][]{
+ {Boolean.TRUE, MediaType.APPLICATION_JSON_TYPE, new AcceptableMediaType("application", "json")},
+ {Boolean.TRUE, MediaType.APPLICATION_JSON_TYPE, new AcceptableMediaType("application", "json", 1000, null)},
+ {Boolean.FALSE, MediaType.APPLICATION_JSON_TYPE, new AcceptableMediaType("application", "json", 500, null)},
+ {Boolean.FALSE, MediaType.APPLICATION_JSON_TYPE, new AcceptableMediaType("application", "xml")}
+ });
+ }
+
+ private final boolean expectEquality;
+ private final MediaType mediaType;
+ private final AcceptableMediaType acceptableMediaType;
+
+ public AcceptableMediaTypeTest(boolean expectEquality, MediaType mediaType, AcceptableMediaType acceptableMediaType) {
+ this.expectEquality = expectEquality;
+ this.mediaType = mediaType;
+ this.acceptableMediaType = acceptableMediaType;
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ if (expectEquality) {
+ Assert.assertEquals("Types not equal.", mediaType, acceptableMediaType);
+ Assert.assertEquals("Types not equal.", acceptableMediaType, mediaType);
+ Assert.assertEquals(
+ String.format("Hash codes not equal for %s and %s.", mediaType.toString(), acceptableMediaType.toString()),
+ mediaType.hashCode(), acceptableMediaType.hashCode());
+ } else {
+ Assert.assertFalse(String.format("False equality of %s and %s", mediaType.toString(), acceptableMediaType.toString()),
+ acceptableMediaType.equals(mediaType));
+ }
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CommittingOutputStreamTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CommittingOutputStreamTest.java
new file mode 100644
index 0000000..5361275
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CommittingOutputStreamTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.message.internal.CommittingOutputStream;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Test the {@link CommittingOutputStream}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class CommittingOutputStreamTest {
+
+ private static class Passed {
+ boolean b;
+
+ public void pass() {
+ b = true;
+ }
+ }
+
+ @Test
+ public void testExactSizeOfBuffer() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupBufferedStreamProvider(passed, baos, cos, 3);
+
+ cos.write((byte) 1);
+ cos.write((byte) 2);
+ cos.write((byte) 3);
+ checkNotYetCommitted(passed, baos, cos);
+ cos.commit();
+ check(baos, new byte[]{1, 2, 3});
+ assertTrue(passed.b);
+ cos.close();
+ }
+
+ private void checkNotYetCommitted(Passed passed, ByteArrayOutputStream baos, CommittingOutputStream cos) {
+ assertFalse(passed.b);
+ assertFalse(cos.isCommitted());
+ check(baos, null);
+ }
+
+ private void checkCommitted(Passed passed, CommittingOutputStream cos) {
+ assertTrue(passed.b);
+ assertTrue(cos.isCommitted());
+ }
+
+ private void setupBufferedStreamProvider(final Passed passed, final ByteArrayOutputStream baos, CommittingOutputStream cos,
+ final int expectedContentLength) {
+ cos.setStreamProvider(new OutboundMessageContext.StreamProvider() {
+ @Override
+ public OutputStream getOutputStream(int contentLength) throws IOException {
+ assertEquals(expectedContentLength, contentLength);
+ passed.pass();
+ return baos;
+ }
+ });
+ cos.enableBuffering(3);
+ }
+
+ private void setupStreamProvider(final Passed passed, final ByteArrayOutputStream baos, CommittingOutputStream cos) {
+ cos.setStreamProvider(new OutboundMessageContext.StreamProvider() {
+
+ @Override
+ public OutputStream getOutputStream(int contentLength) throws IOException {
+ passed.pass();
+ return baos;
+ }
+ });
+
+ }
+
+ @Test
+ public void testExactSizeOfBufferByClose() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupBufferedStreamProvider(passed, baos, cos, 3);
+
+ cos.write((byte) 1);
+ cos.write((byte) 2);
+ cos.write((byte) 3);
+ checkNotYetCommitted(passed, baos, cos);
+ cos.close();
+ check(baos, new byte[]{1, 2, 3});
+ assertTrue(passed.b);
+ }
+
+ @Test
+ public void testLessBytesThanLimit() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupBufferedStreamProvider(passed, baos, cos, 2);
+
+ cos.write((byte) 1);
+ cos.write((byte) 2);
+ checkNotYetCommitted(passed, baos, cos);
+
+ cos.commit();
+
+ check(baos, new byte[]{1, 2});
+ cos.close();
+ assertTrue(passed.b);
+ }
+
+ @Test
+ public void testNoBytes() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupBufferedStreamProvider(passed, baos, cos, 0);
+
+ checkNotYetCommitted(passed, baos, cos);
+
+ cos.commit();
+
+ check(baos, null);
+ cos.close();
+ assertTrue(passed.b);
+ }
+
+ @Test
+ public void testBufferOverflow() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupBufferedStreamProvider(passed, baos, cos, -1);
+
+ cos.write((byte) 1);
+ cos.write((byte) 2);
+ cos.write((byte) 3);
+ checkNotYetCommitted(passed, baos, cos);
+ cos.write((byte) 4);
+ check(baos, new byte[]{1, 2, 3, 4});
+ cos.write((byte) 5);
+ check(baos, new byte[]{1, 2, 3, 4, 5});
+
+ cos.commit();
+
+ check(baos, new byte[]{1, 2, 3, 4, 5});
+ cos.close();
+ }
+
+ @Test
+ public void testNotBufferedOS() throws IOException {
+ final Passed passed = new Passed();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
+ CommittingOutputStream cos = new CommittingOutputStream();
+ setupStreamProvider(passed, baos, cos);
+
+ checkNotYetCommitted(passed, baos, cos);
+ cos.write((byte) 1);
+ checkCommitted(passed, cos);
+ check(baos, new byte[]{1});
+ cos.write((byte) 2);
+ checkCommitted(passed, cos);
+ cos.write((byte) 3);
+ cos.write((byte) 4);
+ check(baos, new byte[]{1, 2, 3, 4});
+ cos.write((byte) 5);
+ check(baos, new byte[]{1, 2, 3, 4, 5});
+
+ cos.commit();
+ checkCommitted(passed, cos);
+ check(baos, new byte[]{1, 2, 3, 4, 5});
+ cos.close();
+ }
+
+ private void check(ByteArrayOutputStream baos, byte... bytes) {
+ assertEquals(bytes == null ? 0 : bytes.length, baos.size());
+
+ if (bytes != null) {
+ final byte[] actualBytes = baos.toByteArray();
+ for (int i = 0; i < bytes.length; i++) {
+ assertEquals(bytes[i], actualBytes[i]);
+ }
+ }
+ }
+
+ @Test
+ public void testPropertiesWithMessageContext() throws IOException {
+ final int size = 20;
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, size);
+ final RuntimeType runtime = RuntimeType.CLIENT;
+
+ checkBufferSize(size, properties, runtime);
+ }
+
+ @Test
+ public void testPropertiesWithMessageContextVeryBigBuffer() throws IOException {
+ final int size = 200000;
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, size);
+ final RuntimeType runtime = RuntimeType.CLIENT;
+
+ checkBufferSize(size, properties, runtime);
+ }
+
+ @Test
+ public void testPropertiesWithMessageContextMissingServerSpecific() throws IOException {
+ final int size = 22;
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, size);
+ properties.put(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER + ".client", size * 2);
+ checkBufferSize(size, properties, RuntimeType.SERVER);
+ }
+
+ @Test
+ public void testPropertiesWithMessageContextMissingServerAtAll() throws IOException {
+ final int size = 22;
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(PropertiesHelper.getPropertyNameForRuntime(
+ CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, RuntimeType.CLIENT), size);
+ checkBufferSize(CommittingOutputStream.DEFAULT_BUFFER_SIZE, properties, RuntimeType.SERVER);
+ checkBufferSize(size, properties, RuntimeType.CLIENT);
+ }
+
+ @Test
+ public void testPropertiesWithMessageContextClientOverrides() throws IOException {
+ final int size = 22;
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, size);
+ properties.put(PropertiesHelper.getPropertyNameForRuntime(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER,
+ RuntimeType.CLIENT), size * 2);
+
+ checkBufferSize(size * 2, properties, RuntimeType.CLIENT);
+ checkBufferSize(size, properties, RuntimeType.SERVER);
+ }
+
+ @Test
+ public void testPropertiesWithMessageContextDefaultNoProps() throws IOException {
+ Map<String, Object> properties = new HashMap<>();
+ final RuntimeType runtime = RuntimeType.CLIENT;
+
+ checkBufferSize(CommittingOutputStream.DEFAULT_BUFFER_SIZE, properties, runtime);
+ }
+
+ private void checkBufferSize(int expectedSize, Map<String, Object> properties, RuntimeType runtime) throws IOException {
+ OutboundMessageContext outboundMessageContext = new OutboundMessageContext();
+ final Passed passed = new Passed();
+ outboundMessageContext.setStreamProvider(new OutboundMessageContext.StreamProvider() {
+ @Override
+ public OutputStream getOutputStream(int contentLength) throws IOException {
+
+ assertEquals(-1, contentLength);
+ passed.pass();
+ return null;
+ }
+ });
+ CommonConfig configuration = new CommonConfig(runtime, ComponentBag.INCLUDE_ALL);
+ configuration.setProperties(properties);
+ outboundMessageContext.enableBuffering(configuration);
+
+ final OutputStream entityStream = outboundMessageContext.getEntityStream();
+ for (int i = 1; (i < 1000000) && (!passed.b); i++) {
+ entityStream.write((byte) 65);
+ if (i >= expectedSize + 1) {
+ break;
+ } else {
+ assertFalse("committed already with byte #" + i, passed.b);
+ }
+ }
+
+ assertTrue(passed.b);
+ }
+
+
+ @Test
+ public void testEnableBuffering() {
+ CommittingOutputStream cos = new CommittingOutputStream();
+ cos.enableBuffering(500);
+ }
+
+ @Test
+ public void testEnableBufferingIllegalStateException() throws IOException {
+ CommittingOutputStream cos = new CommittingOutputStream();
+ cos.setStreamProvider(new OutboundMessageContext.StreamProvider() {
+ @Override
+ public OutputStream getOutputStream(int contentLength) throws IOException {
+ return null;
+ }
+ });
+ cos.write('a');
+ try {
+ cos.enableBuffering(500);
+ fail("should throw IllegalStateException because of late setup of enableBuffering when bytes are already written.");
+ } catch (IllegalStateException e) {
+ System.out.println("this is ok - exception should be thrown: " + e.getMessage());
+ // ok - should be thrown (bytes are already written).
+ }
+ }
+
+ @Test
+ public void testSetStramProviderIllegalStateException1() throws IOException {
+ CommittingOutputStream cos = new CommittingOutputStream();
+ cos.enableBuffering(1);
+ writeAndCheckIllegalState(cos);
+ }
+
+ @Test
+ public void testSetStramProviderIllegalStateException2() throws IOException {
+ CommittingOutputStream cos = new CommittingOutputStream();
+ writeAndCheckIllegalState(cos);
+ }
+
+ private void writeAndCheckIllegalState(CommittingOutputStream cos) throws IOException {
+ try {
+ cos.write('a');
+ cos.write('a');
+ cos.write('a');
+ cos.write('a');
+ cos.write('a');
+ fail("should throw IllegalStateException because of missing stream provider (bytes are already written).");
+ } catch (IllegalStateException e) {
+ System.out.println("this is ok - exception should be thrown: " + e.getMessage());
+ // ok - should be thrown (bytes are already written).
+ }
+ }
+
+}
+
+
+
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java
new file mode 100644
index 0000000..77ce25b
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import javax.ws.rs.core.NewCookie;
+
+import org.glassfish.jersey.message.internal.CookiesParser;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class CookiesParserTest {
+
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
+
+ @Test
+ public void testCaseInsensitiveNewCookieParams() throws Exception {
+ _testCaseInsensitiveNewCookieParams("expires", "max-age", "path", "domain", "comment", "version", "secure", "httponly");
+ _testCaseInsensitiveNewCookieParams("Expires", "Max-Age", "Path", "Domain", "Comment", "Version", "Secure", "HttpOnly");
+ _testCaseInsensitiveNewCookieParams("exPires", "max-aGe", "patH", "doMAin", "Comment", "vErsion", "secuRe", "httPonly");
+ }
+
+ private void _testCaseInsensitiveNewCookieParams(final String expires, final String maxAge, final String path,
+ final String domain, final String comment, final String version,
+ final String secure, final String httpOnly) throws Exception {
+
+ final String header = "foo=bar;"
+ + expires + "=Tue, 15 Jan 2013 21:47:38 GMT;"
+ + maxAge + "=42;"
+ + path + "=/;"
+ + domain + "=.example.com;"
+ + comment + "=Testing;"
+ + version + "=1;"
+ + secure + ";"
+ + httpOnly;
+
+ final NewCookie cookie = CookiesParser.parseNewCookie(header);
+
+ assertThat(cookie.getName(), equalTo("foo"));
+ assertThat(cookie.getValue(), equalTo("bar"));
+
+ assertThat(cookie.getExpiry(), equalTo(dateFormat.parse("Tue, 15 Jan 2013 21:47:38 GMT")));
+ assertThat(cookie.getMaxAge(), equalTo(42));
+ assertThat(cookie.getPath(), equalTo("/"));
+ assertThat(cookie.getDomain(), equalTo(".example.com"));
+ assertThat(cookie.getComment(), equalTo("Testing"));
+ assertThat(cookie.getVersion(), equalTo(1));
+ assertThat(cookie.isSecure(), is(true));
+ assertThat(cookie.isHttpOnly(), is(true));
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/HeaderUtilsTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/HeaderUtilsTest.java
new file mode 100644
index 0000000..c212e1d
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/HeaderUtilsTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.core.AbstractMultivaluedMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.message.internal.HeaderUtils;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * {@link HeaderUtils} unit tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class HeaderUtilsTest {
+
+ public HeaderUtilsTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Test
+ public void testCreateInbound() throws Exception {
+ final MultivaluedMap<String, String> inbound = HeaderUtils.createInbound();
+ assertNotNull(inbound);
+
+ // Test mutability.
+ inbound.putSingle("key", "value");
+ assertEquals("value", inbound.getFirst("key"));
+ }
+
+ @Test
+ public void testEmpty() throws Exception {
+ final MultivaluedMap<String, String> emptyStrings = HeaderUtils.empty();
+ assertNotNull(emptyStrings);
+
+ final MultivaluedMap<String, Object> emptyObjects = HeaderUtils.empty();
+ assertNotNull(emptyObjects);
+
+ // Test immutability.
+ try {
+ emptyStrings.putSingle("key", "value");
+ fail("UnsupportedOperationException expected.");
+ } catch (UnsupportedOperationException ex) {
+ // passed
+ }
+ try {
+ emptyObjects.putSingle("key", "value");
+ fail("UnsupportedOperationException expected.");
+ } catch (UnsupportedOperationException ex) {
+ // passed
+ }
+ }
+
+ @Test
+ public void testCreateOutbound() throws Exception {
+ final MultivaluedMap<String, Object> outbound = HeaderUtils.createOutbound();
+ assertNotNull(outbound);
+
+ // Test mutability.
+ outbound.putSingle("key", "value");
+ assertEquals("value", outbound.getFirst("key"));
+
+ final Object value = new Object();
+ outbound.putSingle("key", value);
+ assertEquals(value, outbound.getFirst("key"));
+ }
+
+ @Test
+ public void testAsString() throws Exception {
+ assertNull(HeaderUtils.asString(null, null));
+
+ final String value = "value";
+ assertSame(value, HeaderUtils.asString(value, null));
+
+ final URI uri = new URI("test");
+ assertEquals(uri.toASCIIString(), HeaderUtils.asString(uri, null));
+ }
+
+ @Test
+ public void testAsStringList() throws Exception {
+ assertNotNull(HeaderUtils.asStringList(null, null));
+ assertTrue(HeaderUtils.asStringList(null, null).isEmpty());
+
+ final URI uri = new URI("test");
+ final List<Object> values = new LinkedList<Object>() {{
+ add("value");
+ add(null);
+ add(uri);
+ }};
+
+ // test string values
+ final List<String> stringList = HeaderUtils.asStringList(values, null);
+ assertEquals(Arrays.asList("value", "[null]", uri.toASCIIString()),
+ stringList);
+
+ // tests live view
+ values.add("value2");
+ assertEquals(Arrays.asList("value", "[null]", uri.toASCIIString(), "value2"),
+ stringList);
+ values.remove(1);
+ assertEquals(Arrays.asList("value", uri.toASCIIString(), "value2"),
+ stringList);
+ }
+
+ @Test
+ public void testAsStringHeaders() throws Exception {
+ assertNull(HeaderUtils.asStringHeaders(null));
+
+ final AbstractMultivaluedMap<String, Object> headers = HeaderUtils.createOutbound();
+
+ headers.putSingle("k1", "value");
+ headers.add("k1", "value2");
+
+ final URI uri = new URI("test");
+ headers.putSingle("k2", uri);
+
+ headers.putSingle("k3", "value3");
+
+ final MultivaluedMap<String, String> stringHeaders = HeaderUtils.asStringHeaders(headers);
+
+ // test string values
+ assertEquals(Arrays.asList("value", "value2"),
+ stringHeaders.get("k1"));
+ assertEquals(Collections.singletonList(uri.toASCIIString()),
+ stringHeaders.get("k2"));
+ assertEquals(Collections.singletonList("value3"),
+ stringHeaders.get("k3"));
+
+ // test live view
+ headers.get("k1").remove(1);
+ headers.add("k2", "value4");
+ headers.remove("k3");
+
+ assertEquals(Collections.singletonList("value"),
+ stringHeaders.get("k1"));
+ assertEquals(Arrays.asList(uri.toASCIIString(), "value4"),
+ stringHeaders.get("k2"));
+ assertFalse(stringHeaders.containsKey("k3"));
+ }
+
+ @Test
+ public void testAsHeaderString() throws Exception {
+ assertNull(HeaderUtils.asHeaderString(null, null));
+
+ final URI uri = new URI("test");
+ final List<Object> values = Arrays.asList("value", null, uri);
+
+ // test string values
+ final String result = HeaderUtils.asHeaderString(values, null);
+ assertEquals("value,[null]," + uri.toASCIIString(), result);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/InboundMessageContextTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/InboundMessageContextTest.java
new file mode 100644
index 0000000..3645513
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/InboundMessageContextTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.message.internal.CookieProvider;
+import org.glassfish.jersey.message.internal.InboundMessageContext;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * {@link org.glassfish.jersey.message.internal.InboundMessageContext} test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class InboundMessageContextTest {
+
+ public InboundMessageContextTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ private static InboundMessageContext createInboundMessageContext() {
+ return new InboundMessageContext() {
+ @Override
+ protected Iterable<ReaderInterceptor> getReaderInterceptors() {
+ return Collections.emptyList();
+ }
+ };
+ }
+
+ @Test
+ public void testNoLength() {
+ InboundMessageContext r = createInboundMessageContext();
+ assertEquals(-1, r.getLength());
+ }
+
+ @Test
+ public void testRequestCookies() throws URISyntaxException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.COOKIE, "oreo=chocolate");
+ r.header(HttpHeaders.COOKIE, "nilla=vanilla");
+ assertEquals(r.getRequestCookies().size(), 2);
+ assertTrue(r.getRequestCookies().containsKey("oreo"));
+ assertTrue(r.getRequestCookies().containsKey("nilla"));
+ CookieProvider cp = new CookieProvider();
+ assertTrue(r.getRequestCookies().containsValue(cp.fromString("oreo=chocolate")));
+ assertTrue(r.getRequestCookies().containsValue(cp.fromString("nilla=vanilla")));
+ }
+
+ @Test
+ public void testDate() throws URISyntaxException, ParseException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.DATE, "Tue, 29 Jan 2002 22:14:02 -0500");
+ SimpleDateFormat f = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
+ Date date = f.parse("Tue, 29 Jan 2002 22:14:02 -0500");
+ assertEquals(r.getDate(), date);
+ }
+
+ @Test
+ public void testHeader() throws URISyntaxException, ParseException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.ACCEPT, "application/xml, text/plain");
+ r.header(HttpHeaders.ACCEPT, "application/json");
+ r.header("FOO", "");
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("application/xml"));
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("text/plain"));
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("application/json"));
+ assertEquals(r.getHeaderString("FOO").length(), 0);
+ assertNull(r.getHeaderString("BAR"));
+ }
+
+ @Test
+ public void testHeaderMap() throws URISyntaxException, ParseException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.ACCEPT, "application/xml, text/plain");
+ r.header(HttpHeaders.ACCEPT, "application/json");
+ r.header("Allow", "GET, PUT");
+ r.header("Allow", "POST");
+ assertTrue(r.getHeaders().containsKey(HttpHeaders.ACCEPT));
+ assertTrue(r.getHeaders().containsKey("Allow"));
+ assertTrue(r.getHeaders().get(HttpHeaders.ACCEPT).contains("application/json"));
+ assertTrue(r.getHeaders().get("Allow").contains("POST"));
+ }
+
+ @Test
+ public void testAllowedMethods() throws URISyntaxException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header("Allow", "GET, PUT");
+ r.header("Allow", "POST");
+ assertEquals(3, r.getAllowedMethods().size());
+ assertTrue(r.getAllowedMethods().contains("GET"));
+ assertTrue(r.getAllowedMethods().contains("PUT"));
+ assertTrue(r.getAllowedMethods().contains("POST"));
+ assertFalse(r.getAllowedMethods().contains("DELETE"));
+ }
+
+ @Test
+ public void testResponseCookies() throws URISyntaxException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.SET_COOKIE, "oreo=chocolate");
+ r.header(HttpHeaders.SET_COOKIE, "nilla=vanilla");
+ assertEquals(2, r.getResponseCookies().size());
+ assertTrue(r.getResponseCookies().containsKey("oreo"));
+ assertTrue(r.getResponseCookies().containsKey("nilla"));
+ }
+
+ @Test
+ public void testEntityTag() throws URISyntaxException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.ETAG, "\"tag\"");
+ assertEquals(EntityTag.valueOf("\"tag\""), r.getEntityTag());
+ }
+
+ @Test
+ public void testLastModified() throws URISyntaxException, ParseException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.LAST_MODIFIED, "Tue, 29 Jan 2002 22:14:02 -0500");
+ SimpleDateFormat f = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
+ Date date = f.parse("Tue, 29 Jan 2002 22:14:02 -0500");
+ assertEquals(date, r.getLastModified());
+ }
+
+ @Test
+ public void testLocation() throws URISyntaxException {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.LOCATION, "http://example.org/app");
+ assertEquals(URI.create("http://example.org/app"), r.getLocation());
+ }
+
+ @Test
+ public void testGetLinks() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("http://example.org/app/link1").param("produces", "application/json").param("method",
+ "GET").rel("self").build();
+ Link link2 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method",
+ "PUT").rel("self").build();
+ r.header("Link", link1.toString());
+ r.header("Link", link2.toString());
+ assertEquals(2, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ assertTrue(r.getLinks().contains(link2));
+ }
+
+ @Test
+ public void testGetLinksWithCommaInUri() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("http://example.org/app/foo,bar").param("produces", "application/json").param("method",
+ "GET").rel("self").build();
+ r.header("Link", link1.toString());
+ assertEquals(1, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ }
+
+ @Test
+ public void testGetLinksWithMultipleLinksInOneHeaderAndCommaInUri() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("https://example.org/one/api/groups?foo,page=2").rel("next").build();
+ Link link2 = Link.fromUri("https://example.org/one/api/groups?bar,page=39").rel("last").build();
+ r.header("Link", "<https://example.org/one/api/groups?foo,page=2>; rel=\"next\", <https://example.org/one/api/groups?bar,page=39>; rel=\"last\"");
+ assertEquals(2, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ assertTrue(r.getLinks().contains(link2));
+ }
+
+ @Test
+ public void testGetLinksWithMultipleLinksInOneHeader() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("https://example.org/one/api/groups?page=2").rel("next").build();
+ Link link2 = Link.fromUri("https://example.org/one/api/groups?page=39").rel("last").build();
+ r.header("Link", "<https://example.org/one/api/groups?page=2>; rel=\"next\", <https://example.org/one/api/groups?page=39>; rel=\"last\"");
+ assertEquals(2, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ assertTrue(r.getLinks().contains(link2));
+ }
+
+ @Test
+ public void testGetLinksWithMultipleLinksInOneHeaderWithLtInValue() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("https://example.org/one/api/groups?page=2").rel("next").param("foo", "<bar>").build();
+ Link link2 = Link.fromUri("https://example.org/one/api/groups?page=39").rel("last").param("bar", "<<foo").build();
+ r.header("Link", "<https://example.org/one/api/groups?page=2>; rel=\"next\"; foo=\"<bar>\", <https://example.org/one/api/groups?page=39>; rel=\"last\"; bar=\"<<foo\"");
+ assertEquals(2, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ assertTrue(r.getLinks().contains(link2));
+ }
+
+ @Test
+ public void testGetLink() {
+ InboundMessageContext r = createInboundMessageContext();
+ Link link1 = Link.fromUri("http://example.org/app/link1").param("produces", "application/json").param("method",
+ "GET").rel("self").build();
+ Link link2 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method",
+ "PUT").rel("update").build();
+ Link link3 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method",
+ "POST").rel("update").build();
+ r.header("Link", link1.toString());
+ r.header("Link", link2.toString());
+ r.header("Link", link3.toString());
+ assertTrue(r.getLink("self").equals(link1));
+ assertTrue(r.getLink("update").equals(link2) || r.getLink("update").equals(link3));
+ }
+
+ @Test
+ public void testGetAllowedMethods() {
+ InboundMessageContext r = createInboundMessageContext();
+ r.header(HttpHeaders.ALLOW, "a,B,CcC,dDd");
+ final Set<String> allowedMethods = r.getAllowedMethods();
+ assertEquals(4, allowedMethods.size());
+ assertTrue(allowedMethods.contains("A"));
+ assertTrue(allowedMethods.contains("B"));
+ assertTrue(allowedMethods.contains("CCC"));
+ assertTrue(allowedMethods.contains("DDD"));
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/JerseyLinkTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/JerseyLinkTest.java
new file mode 100644
index 0000000..7e25df8
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/JerseyLinkTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.net.URI;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests for LinkTest class.
+ *
+ * @author Santiago Pericas-Geertsen (Santiago.PericasGeertsen at oracle.com)
+ */
+public class JerseyLinkTest {
+
+ @Path("/myresource")
+ static class MyResource {
+
+ @GET
+ @Produces("text/plain")
+ public String self() {
+ return "myself";
+ }
+
+ @GET
+ @Produces("application/xml")
+ public String notSelf() {
+ return "<xml>notSelf</xml>";
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ RuntimeDelegate.setInstance(null);
+ }
+
+ @Test
+ public void testGetUri() {
+ URI u = URI.create("http://example.org/app/link1");
+ Link l1 = Link.fromUri("http://example.org/app/link1").param("foo1", "bar1").param("foo2", "bar2").build();
+ assertEquals(l1.getUri(), u);
+ assertEquals(l1.getUriBuilder().build(), u);
+ }
+
+ @Test
+ public void testToString() {
+ Link link = Link.fromUri("http://example.org/app/link1").rel("self").build();
+ assertEquals("<http://example.org/app/link1>; rel=\"self\"", link.toString());
+ }
+
+ @Test
+ public void testGetters() {
+ Link link = Link.fromUri("http://example.org/app/link1").rel("self").type("text/plain").build();
+ assertEquals(URI.create("http://example.org/app/link1"), link.getUri());
+ assertEquals("self", link.getRel());
+ assertEquals(null, link.getTitle());
+ assertEquals("text/plain", link.getType());
+ assertEquals(2, link.getParams().size());
+ }
+
+ /**
+ * Regression test for JERSEY-1378 fix.
+ */
+ @Test
+ public void buildRelativeLinkTest() {
+ assertEquals(URI.create("aa%20bb"), Link.fromUri("aa bb").build().getUri());
+ }
+
+ /**
+ * Reproducer for JERSEY-2387: IAE expected on unresolved URI template parameters.
+ */
+ @Test
+ public void testLinkBuilderWithUnresolvedTemplates() {
+ Link.Builder linkBuilder;
+ try {
+ linkBuilder = Link.fromUri("scheme://authority/{x1}/{x2}/{x3}");
+ linkBuilder.build("p");
+ fail("IllegalArgumentException is expected to be thrown from Link.Builder when there are unresolved templates.");
+ } catch (IllegalArgumentException expected) {
+ // exception expected, move on...
+ }
+ try {
+ linkBuilder = Link.fromUri("scheme://authority/{x1}/{x2}/{x3}");
+ linkBuilder.build();
+ fail("IllegalArgumentException is expected to be thrown from Link.Builder when there are unresolved templates.");
+ } catch (IllegalArgumentException expected) {
+ // exception expected, move on...
+ }
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/LinkProviderTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/LinkProviderTest.java
new file mode 100644
index 0000000..0f8f3c7
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/LinkProviderTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import javax.ws.rs.core.Link;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for LinkProvider class.
+ *
+ * @author Santiago Pericas-Geertsen (Santiago.PericasGeertsen at oracle.com)
+ */
+public class LinkProviderTest {
+
+ @Before
+ public void setUp() throws Exception {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ RuntimeDelegate.setInstance(null);
+ }
+
+ @Test
+ public void testValueOf() {
+ final Link l1 = Link.fromUri("http://example.org/app/link1").build();
+ Link l2 = Link.valueOf("<http://example.org/app/link1>");
+ assertEquals(l1, l2);
+ l2 = Link.valueOf(" <http://example.org/app/link1>");
+ assertEquals(l1, l2);
+ l2 = Link.valueOf(" <http://example.org/app/link1> ");
+ assertEquals(l1, l2);
+ }
+
+ @Test
+ public void testValueOfExceptions() {
+ int nOfExceptions = 0;
+ try {
+ Link.valueOf("http://example.org/app/link1>");
+ } catch (final IllegalArgumentException e) {
+ nOfExceptions++;
+ }
+ try {
+ Link.valueOf("<http://example.org/app/link1");
+ } catch (final IllegalArgumentException e) {
+ nOfExceptions++;
+ }
+ try {
+ Link.valueOf("http://example.org/app/link1");
+ } catch (final IllegalArgumentException e) {
+ nOfExceptions++;
+ }
+ assertEquals(nOfExceptions, 3);
+ }
+
+ @Test
+ public void testValueOfParams() {
+ final Link l1 = Link.fromUri("http://example.org/app/link1").param("foo1", "bar1").param("foo2", "bar2").build();
+ Link l2 = Link.valueOf("<http://example.org/app/link1>; foo1=\"bar1\"; foo2 = \"bar2\"");
+ assertEquals(l1, l2);
+ l2 = Link.valueOf("<http://example.org/app/link1>; foo2=\"bar2\"; foo1= \"bar1\"");
+ assertEquals(l1, l2);
+ l2 = Link.valueOf("<http://example.org/app/link1>; foo1=\"bar1\"; foo2=\"bar2\"");
+ assertEquals(l1, l2);
+ l2 = Link.valueOf("< http://example.org/app/link1 >; foo1=\"bar1\"; foo2=\"bar2\"");
+ assertEquals(l1, l2);
+ }
+
+ @Test
+ public void testRoundTrip() {
+ final Link l1 = Link.fromUri("http://example.org/app/link1").param("foo1", "bar1").param("foo2", "bar2").build();
+ assertEquals(l1, Link.valueOf(l1.toString()));
+ final Link l2 = Link.valueOf("<http://example.org/app/link1>; foo1=\"bar1\"; foo2 = \"bar2\"");
+ assertEquals(l1, l2);
+ }
+
+ @Test
+ public void testWithoutDoubleQuotes() {
+ final Link l1 = Link.fromUri("http://example.org/app/link1").param("foo1", "bar1").param("foo2", "bar2").build();
+ assertEquals(l1, Link.valueOf(l1.toString()));
+ final Link l2 = Link.valueOf("<http://example.org/app/link1>; foo1=bar1; foo2 = bar2");
+ assertEquals(l1, l2);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MatchingEntityTagTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MatchingEntityTagTest.java
new file mode 100644
index 0000000..40d457b
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MatchingEntityTagTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.text.ParseException;
+import java.util.Set;
+
+import javax.ws.rs.core.EntityTag;
+
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+import org.glassfish.jersey.message.internal.MatchingEntityTag;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * {@link MatchingEntityTag} unit tests ported from Jersey 1.x.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class MatchingEntityTagTest {
+
+ @Test
+ public void testOneEntityTag() throws Exception {
+ String header = "\"1\"";
+ Set<MatchingEntityTag> s = HttpHeaderReader.readMatchingEntityTag(header);
+
+ assertEquals(1, s.size());
+
+ assertTrue(s.contains(new EntityTag("1")));
+ }
+
+ @Test
+ public void testMultipleEntityTag() throws Exception {
+ String header = "\"1\", W/\"2\", \"3\"";
+ Set<MatchingEntityTag> s = HttpHeaderReader.readMatchingEntityTag(header);
+
+ assertEquals(3, s.size());
+
+ assertTrue(s.contains(new EntityTag("1")));
+
+ assertTrue(s.contains(new EntityTag("2", true)));
+
+ assertTrue(s.contains(new EntityTag("3")));
+ }
+
+ @Test
+ public void testAnyMatch() throws Exception {
+ String header = "*";
+ Set<MatchingEntityTag> s = HttpHeaderReader.readMatchingEntityTag(header);
+
+ assertThat(s.size(), is(equalTo(0)));
+ assertThat(MatchingEntityTag.ANY_MATCH, is(s));
+ }
+
+ /**
+ * Reproducer for JERSEY-1278.
+ */
+ @Test
+ public void testBadEntityTag() {
+ String header = "1\"";
+ try {
+ HttpHeaderReader.readMatchingEntityTag(header);
+ fail("ParseException expected");
+ } catch (ParseException pe) {
+ assertThat(pe.getMessage(), containsString(header));
+ }
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MediaTypesTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MediaTypesTest.java
new file mode 100644
index 0000000..12dcd81
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/MediaTypesTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+import org.glassfish.jersey.message.internal.MediaTypes;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * MediaTypes utility method tests.
+ *
+ * @author Miroslav Fuksa
+ * @author Marek Potociar (marek.potociar at oralce.com)
+ */
+public class MediaTypesTest {
+
+ @Test
+ public void testConvertToString() {
+ final List<MediaType> emptyList = Collections.emptyList();
+ Assert.assertEquals("", MediaTypes.convertToString(emptyList));
+
+
+ Assert.assertEquals("\"text/plain\"", MediaTypes.convertToString(Collections.singleton(MediaType.TEXT_PLAIN_TYPE)));
+
+ Assert.assertEquals("\"text/plain\", \"application/json\"",
+ MediaTypes.convertToString(Arrays.asList(MediaType.TEXT_PLAIN_TYPE,
+ MediaType.APPLICATION_JSON_TYPE)));
+
+ Assert.assertEquals("\"text/plain\", \"application/json\", \"text/html\"",
+ MediaTypes.convertToString(Arrays.asList(MediaType.TEXT_PLAIN_TYPE,
+ MediaType.APPLICATION_JSON_TYPE,
+ MediaType.TEXT_HTML_TYPE)));
+ }
+
+ @Test
+ public void testMostSpecific() {
+
+ MediaType m1;
+ MediaType m2;
+
+ /* wildcard type */
+ m1 = MediaType.WILDCARD_TYPE;
+
+ // wildcard type #1 - concrete type wins
+ m2 = new MediaType("foo", "bar");
+ _testMostSpecific(m1, m2, m2);
+ _testMostSpecific(m2, m1, m2);
+
+ // wildcard type #2 - wildcard subtype wins
+ m2 = new MediaType("foo", "*");
+ _testMostSpecific(m1, m2, m2);
+ _testMostSpecific(m2, m1, m2);
+
+ // wildcard type #3 - first parameter wins
+ m2 = new MediaType("*", "*");
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m2);
+
+ /* wildcard subtype */
+ m1 = new MediaType("moo", "*");
+
+ // wildcard subtype #1 - concrete type wins
+ m2 = new MediaType("foo", "bar");
+ _testMostSpecific(m1, m2, m2);
+ _testMostSpecific(m2, m1, m2);
+
+ // wildcard subtype #2 - first parameter in method wins
+ m2 = new MediaType("foo", "*");
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m2);
+
+ /* concrete types */
+ // concrete types - first parameter in method wins
+ m1 = new MediaType("moo", "boo");
+ m2 = new MediaType("foo", "bar");
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m2);
+
+ /* concrete type with parameters */
+ m1 = new MediaType("foo", "bar", asMap("p1=v1;p2=v2"));
+
+ // concrete type with parameters #1 - wildcard type looses
+ m2 = MediaType.WILDCARD_TYPE;
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m1);
+
+ // concrete type with parameters #2 - wildcard subtype looses
+ m2 = new MediaType("foo", "*");
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m1);
+
+ // concrete type with parameters #3 - concrete parameter-less type looses
+ m2 = new MediaType("foo", "baz");
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m1);
+
+ // concrete type with parameters #4 - type with less parameters type looses
+ m2 = new MediaType("foo", "baz", asMap("a1=b1"));
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m1);
+
+ // both concrete types with parameters #5 - first parameter in method wins
+ m2 = new MediaType("foo", "baz", asMap("a1=b1;a2=b2"));
+ _testMostSpecific(m1, m2, m1);
+ _testMostSpecific(m2, m1, m2);
+ }
+
+ private static void _testMostSpecific(MediaType m1, MediaType m2, MediaType result) {
+ assertThat("Unexpected media type selected to be most specific.",
+ MediaTypes.mostSpecific(m1, m2), is(result));
+ }
+
+ /**
+ * Creates a map from HTTP header parameter strings.
+ *
+ * @param parameters HTTP header parameters string.
+ * @return HTTP header parameters map.
+ */
+ public static Map<String, String> asMap(String parameters) {
+ HttpHeaderReader reader = HttpHeaderReader.newInstance(";" + parameters);
+
+ if (reader.hasNext()) {
+ try {
+ return HttpHeaderReader.readParameters(reader);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return Collections.emptyMap();
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseBuilderTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseBuilderTest.java
new file mode 100644
index 0000000..fb68693
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JaxrsResponseViewTest class.
+ *
+ * @author Santiago Pericas-Geertsen (santiago.pericasgeertsen at oracle.com)
+ */
+public class OutboundJaxrsResponseBuilderTest {
+
+ /**
+ * Create test class.
+ */
+ public OutboundJaxrsResponseBuilderTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ /**
+ * Test media type header setting, retrieval.
+ */
+ @Test
+ public void testMediaType() {
+ final Response r = new OutboundJaxrsResponse.Builder(new OutboundMessageContext())
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML)
+ .build();
+ assertEquals(204, r.getStatus());
+ assertEquals(Response.Status.NO_CONTENT, r.getStatusInfo());
+ assertEquals(MediaType.TEXT_HTML_TYPE, r.getMediaType());
+ }
+
+ @Test
+ public void testIssue1297Fix() {
+ final Response response = new OutboundJaxrsResponse.Builder(new OutboundMessageContext())
+ .status(Response.Status.OK)
+ .entity("1234567890")
+ .build();
+ final int len = response.getLength();
+ assertEquals(-1, len);
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseTest.java
new file mode 100644
index 0000000..0fc241f
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundJaxrsResponseTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * OutboundJaxrsResponse unit tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class OutboundJaxrsResponseTest {
+
+ private static class TestInputStream extends ByteArrayInputStream {
+
+ private boolean isRead;
+ private boolean isClosed;
+
+ private TestInputStream() {
+ super("test".getBytes());
+ }
+
+ @Override
+ public synchronized int read() {
+ final int read = super.read();
+ isRead = read == -1;
+ return read;
+ }
+
+ @Override
+ public synchronized int read(byte[] b, int off, int len) {
+ final int read = super.read(b, off, len);
+ isRead = read == -1;
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ final int read = super.read(b);
+ isRead = read == -1;
+ return read;
+ }
+
+ @Override
+ public void close() throws IOException {
+ isClosed = true;
+ super.close();
+ }
+ }
+
+ private static final OutboundMessageContext.StreamProvider TEST_PROVIDER
+ = new OutboundMessageContext.StreamProvider() {
+ @Override
+ public OutputStream getOutputStream(int contentLength) throws IOException {
+ return new ByteArrayOutputStream();
+ }
+ };
+
+ private Response.ResponseBuilder rb;
+
+ /**
+ * Create test class.
+ */
+ public OutboundJaxrsResponseTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Before
+ public void setUp() {
+ rb = new OutboundJaxrsResponse.Builder(new OutboundMessageContext()).status(Response.Status.OK);
+ }
+
+
+ /**
+ * Test of empty entity buffering.
+ */
+ @Test
+ public void testBufferEmptyEntity() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ assertFalse("Buffer entity should return 'false' if no entity.", r.bufferEntity());
+ }
+
+ /**
+ * Test of non-stream entity buffering.
+ */
+ @Test
+ public void testBufferNonStreamEntity() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(new Object()).build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ assertFalse("Buffer entity should return 'false' for non-stream entity.", r.bufferEntity());
+ }
+
+ /**
+ * Test of stream entity buffering.
+ */
+ @Test
+ public void testBufferStreamEntity() {
+ TestInputStream tis = new TestInputStream();
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(tis).build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ assertTrue("Buffer entity should return 'true' for stream entity.", r.bufferEntity());
+ assertTrue("Second call to buffer entity should return 'true' for stream entity.", r.bufferEntity()); // second call
+ assertTrue("Buffered stream has not been fully read.", tis.isRead);
+ assertTrue("Buffered stream has not been closed after buffering.", tis.isClosed);
+ }
+
+ /**
+ * Test of closing response with empty entity.
+ */
+ @Test
+ public void testCloseEmptyEntity() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+ }
+
+ /**
+ * Test of closing response with non-stream entity.
+ */
+ @Test
+ public void testCloseNonStreamEntity() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(new Object()).build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+ }
+
+ /**
+ * Test of closing response with stream entity.
+ */
+ @Test
+ public void testCloseStreamEntity() {
+ TestInputStream tis = new TestInputStream();
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(tis).build());
+ r.getContext().setStreamProvider(TEST_PROVIDER);
+
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+
+ assertFalse("Unbuffered closed response stream entity should not be read.", tis.isRead);
+ assertTrue("Closed response stream entity should have been closed.", tis.isClosed);
+ }
+
+ /**
+ * Test of closing response with empty entity.
+ */
+ @Test
+ public void testCloseEmptyEntityNoStreamProvider() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.build());
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+ }
+
+ /**
+ * Test of closing response with non-stream entity.
+ */
+ @Test
+ public void testCloseNonStreamEntityNoStreamProvider() {
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(new Object()).build());
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+ }
+
+ /**
+ * Test of closing response with stream entity.
+ */
+ @Test
+ public void testCloseStreamEntityNoStreamProvider() {
+ TestInputStream tis = new TestInputStream();
+ final OutboundJaxrsResponse r = OutboundJaxrsResponse.from(rb.entity(tis).build());
+ r.close();
+ try {
+ r.bufferEntity();
+ fail("IllegalStateException expected when buffering entity on closed response.");
+ } catch (IllegalStateException ex) {
+ // ok
+ }
+ r.close(); // second call should pass
+
+ assertFalse("Unbuffered closed response stream entity should not be read.", tis.isRead);
+ assertTrue("Closed response stream entity should have been closed.", tis.isClosed);
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java
new file mode 100644
index 0000000..cdf2a03
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.message.internal.CookieProvider;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+
+import org.junit.Test;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * {@link OutboundMessageContext} test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class OutboundMessageContextTest {
+
+ public OutboundMessageContextTest() {
+ RuntimeDelegate.setInstance(new TestRuntimeDelegate());
+ }
+
+ @Test
+ public void testAcceptableMediaTypes() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/xml, text/plain");
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/json");
+
+ final List<MediaType> acceptableMediaTypes = r.getAcceptableMediaTypes();
+
+ assertThat(acceptableMediaTypes.size(), equalTo(3));
+ assertThat(acceptableMediaTypes,
+ contains(MediaType.APPLICATION_XML_TYPE, MediaType.TEXT_PLAIN_TYPE, MediaType.APPLICATION_JSON_TYPE));
+ }
+
+ @Test
+ public void testAcceptableLanguages() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.ACCEPT_LANGUAGE, "en-gb;q=0.8, en;q=0.7");
+ r.getHeaders().add(HttpHeaders.ACCEPT_LANGUAGE, "de");
+ assertEquals(r.getAcceptableLanguages().size(), 3);
+ assertTrue(r.getAcceptableLanguages().contains(Locale.UK));
+ assertTrue(r.getAcceptableLanguages().contains(Locale.ENGLISH));
+ assertTrue(r.getAcceptableLanguages().contains(Locale.GERMAN));
+ }
+
+ @Test
+ public void testRequestCookies() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.COOKIE, "oreo=chocolate");
+ r.getHeaders().add(HttpHeaders.COOKIE, "nilla=vanilla");
+ assertEquals(r.getRequestCookies().size(), 2);
+ assertTrue(r.getRequestCookies().containsKey("oreo"));
+ assertTrue(r.getRequestCookies().containsKey("nilla"));
+ CookieProvider cp = new CookieProvider();
+ assertTrue(r.getRequestCookies().containsValue(cp.fromString("oreo=chocolate")));
+ assertTrue(r.getRequestCookies().containsValue(cp.fromString("nilla=vanilla")));
+ }
+
+ @Test
+ public void testDate() throws URISyntaxException, ParseException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.DATE, "Tue, 29 Jan 2002 22:14:02 -0500");
+ SimpleDateFormat f = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
+ Date date = f.parse("Tue, 29 Jan 2002 22:14:02 -0500");
+ assertEquals(r.getDate(), date);
+ }
+
+ @Test
+ public void testHeader() throws URISyntaxException, ParseException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/xml, text/plain");
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/json");
+ r.getHeaders().add("FOO", "");
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("application/xml"));
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("text/plain"));
+ assertTrue(r.getHeaderString(HttpHeaders.ACCEPT).contains("application/json"));
+ assertEquals(r.getHeaderString("FOO").length(), 0);
+ assertNull(r.getHeaderString("BAR"));
+ }
+
+ @Test
+ public void testHeaderMap() throws URISyntaxException, ParseException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/xml, text/plain");
+ r.getHeaders().add(HttpHeaders.ACCEPT, "application/json");
+ r.getHeaders().add("Allow", "GET, PUT");
+ r.getHeaders().add("Allow", "POST");
+ assertTrue(r.getHeaders().containsKey(HttpHeaders.ACCEPT));
+ assertTrue(r.getHeaders().containsKey("Allow"));
+ assertTrue(r.getHeaders().get(HttpHeaders.ACCEPT).contains("application/json"));
+ assertTrue(r.getHeaders().get("Allow").contains("POST"));
+ }
+
+ @Test
+ public void testAllowedMethods() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add("Allow", "GET, PUT");
+ r.getHeaders().add("Allow", "POST");
+ assertEquals(3, r.getAllowedMethods().size());
+ assertTrue(r.getAllowedMethods().contains("GET"));
+ assertTrue(r.getAllowedMethods().contains("PUT"));
+ assertTrue(r.getAllowedMethods().contains("POST"));
+ assertFalse(r.getAllowedMethods().contains("DELETE"));
+ }
+
+ @Test
+ public void testResponseCookies() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.SET_COOKIE, "oreo=chocolate");
+ r.getHeaders().add(HttpHeaders.SET_COOKIE, "nilla=vanilla");
+ assertEquals(2, r.getResponseCookies().size());
+ assertTrue(r.getResponseCookies().containsKey("oreo"));
+ assertTrue(r.getResponseCookies().containsKey("nilla"));
+ }
+
+ @Test
+ public void testEntityTag() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.ETAG, "\"tag\"");
+ assertEquals(EntityTag.valueOf("\"tag\""), r.getEntityTag());
+ }
+
+ @Test
+ public void testLastModified() throws URISyntaxException, ParseException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.LAST_MODIFIED, "Tue, 29 Jan 2002 22:14:02 -0500");
+ SimpleDateFormat f = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
+ Date date = f.parse("Tue, 29 Jan 2002 22:14:02 -0500");
+ assertEquals(date, r.getLastModified());
+ }
+
+ @Test
+ public void testLocation() throws URISyntaxException {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add(HttpHeaders.LOCATION, "http://example.org/app");
+ assertEquals(URI.create("http://example.org/app"), r.getLocation());
+ }
+
+ @Test
+ public void testGetLinks() {
+ OutboundMessageContext r = new OutboundMessageContext();
+ Link link1 = Link.fromUri("http://example.org/app/link1").param("produces", "application/json").param("method", "GET").rel("self").build();
+ Link link2 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method", "PUT").rel("self").build();
+ r.getHeaders().add("Link", link1.toString());
+ r.getHeaders().add("Link", link2.toString());
+ assertEquals(2, r.getLinks().size());
+ assertTrue(r.getLinks().contains(link1));
+ assertTrue(r.getLinks().contains(link2));
+ }
+
+ @Test
+ public void testGetLink() {
+ OutboundMessageContext r = new OutboundMessageContext();
+ Link link1 = Link.fromUri("http://example.org/app/link1").param("produces", "application/json").param("method", "GET").rel("self").build();
+ Link link2 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method", "PUT").rel("update").build();
+ Link link3 = Link.fromUri("http://example.org/app/link2").param("produces", "application/xml").param("method", "POST").rel("update").build();
+ r.getHeaders().add("Link", link1.toString());
+ r.getHeaders().add("Link", link2.toString());
+ r.getHeaders().add("Link", link3.toString());
+ assertTrue(r.getLink("self").equals(link1));
+ assertTrue(r.getLink("update").equals(link2) || r.getLink("update").equals(link3));
+ }
+
+ @Test
+ public void testGetLength() {
+ OutboundMessageContext r = new OutboundMessageContext();
+ r.getHeaders().add("Content-Length", 50);
+ assertEquals(50, r.getLengthLong());
+ }
+
+ @Test
+ public void testGetLength_tooLongForInt() {
+ OutboundMessageContext r = new OutboundMessageContext();
+ long length = Integer.MAX_VALUE + 5L;
+ r.getHeaders().add("Content-Length", length);
+
+
+ assertEquals(length, r.getLengthLong());
+
+ // value is not a valid integer -> ProcessingException is thrown.
+ try {
+ r.getLength();
+ } catch (ProcessingException e) {
+ return;
+ }
+
+ fail();
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/QualitySourceMediaTypeTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/QualitySourceMediaTypeTest.java
new file mode 100644
index 0000000..249bc6c
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/QualitySourceMediaTypeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.message.internal;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.QualitySourceMediaType;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Quality source media type unit tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class QualitySourceMediaTypeTest {
+ @Parameterized.Parameters
+ // expected result, media type, quality source media type
+ public static List<Object[]> testBeds() {
+ return Arrays.asList(new Object[][]{
+ {Boolean.TRUE, MediaType.APPLICATION_JSON_TYPE, new QualitySourceMediaType("application", "json")},
+ {Boolean.TRUE, MediaType.APPLICATION_JSON_TYPE, new QualitySourceMediaType("application", "json", 1000, null)},
+ {Boolean.FALSE, MediaType.APPLICATION_JSON_TYPE, new QualitySourceMediaType("application", "json", 500, null)},
+ {Boolean.FALSE, MediaType.APPLICATION_JSON_TYPE, new QualitySourceMediaType("application", "xml")}
+ });
+ }
+
+ private final boolean expectEquality;
+ private final MediaType mediaType;
+ private final QualitySourceMediaType qsMediaType;
+
+ public QualitySourceMediaTypeTest(boolean expectEquality, MediaType mediaType, QualitySourceMediaType qsMediaType) {
+ this.expectEquality = expectEquality;
+ this.mediaType = mediaType;
+ this.qsMediaType = qsMediaType;
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ if (expectEquality) {
+ Assert.assertEquals("Types not equal.", mediaType, qsMediaType);
+ Assert.assertEquals("Types not equal.", qsMediaType, mediaType);
+ Assert.assertEquals(
+ String.format("Hash codes not equal for %s and %s.", mediaType.toString(), qsMediaType.toString()),
+ mediaType.hashCode(), qsMediaType.hashCode());
+ } else {
+ Assert.assertFalse(String.format("False equality of %s and %s", mediaType.toString(), qsMediaType.toString()),
+ qsMediaType.equals(mediaType));
+ }
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/model/internal/CommonConfigTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/model/internal/CommonConfigTest.java
new file mode 100644
index 0000000..c96f28b
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/model/internal/CommonConfigTest.java
@@ -0,0 +1,1000 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.model.internal;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.ProviderBinder;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.model.ContractProvider;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
+import org.glassfish.jersey.model.internal.RankedComparator;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Test cases for {@link javax.ws.rs.core.Configuration}.
+ *
+ * @author Michal Gajdos
+ */
+public class CommonConfigTest {
+
+ private CommonConfig config;
+
+ @Before
+ public void setUp() throws Exception {
+ config = new CommonConfig(null, ComponentBag.INCLUDE_ALL);
+ }
+
+ @Test
+ public void testGetProperties() throws Exception {
+ try {
+ config.getConfiguration().getProperties().put("foo", "bar");
+ fail("Returned properties collection should be immutable.");
+ } catch (final Exception e) {
+ // OK.
+ }
+ }
+
+ @Test
+ public void testSetProperties() throws Exception {
+ config = config.property("foo", "bar");
+ assertEquals("bar", config.getConfiguration().getProperty("foo"));
+
+ final Map<String, String> properties = new HashMap<>();
+ properties.put("hello", "world");
+ config = config.setProperties(properties);
+
+ assertEquals(1, config.getConfiguration().getProperties().size());
+ assertEquals("world", config.getConfiguration().getProperty("hello"));
+
+ properties.put("one", "two");
+ assertEquals(1, config.getConfiguration().getProperties().size());
+ assertNull(config.getConfiguration().getProperty("one"));
+
+ config = config.setProperties(new HashMap<>());
+ assertTrue(config.getConfiguration().getProperties().isEmpty());
+ }
+
+ @Test
+ public void testSetGetProperty() throws Exception {
+ config = config.property("foo", "bar");
+ assertEquals("bar", config.getConfiguration().getProperty("foo"));
+
+ config.property("hello", "world");
+ config.property("foo", null);
+
+ assertEquals(null, config.getConfiguration().getProperty("foo"));
+ assertEquals(1, config.getConfiguration().getProperties().size());
+ }
+
+ public static class EmptyFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext configuration) {
+ return true;
+ }
+ }
+
+ public static class UnconfigurableFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext configuration) {
+ return false;
+ }
+ }
+
+ public static class ComplexEmptyProvider implements ReaderInterceptor, ContainerRequestFilter, ExceptionMapper {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ // Do nothing.
+ }
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return context.proceed();
+ }
+
+ @Override
+ public Response toResponse(final Throwable exception) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static class ComplexEmptyProviderFeature extends ComplexEmptyProvider implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext configuration) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Test
+ public void testReplaceWith() throws Exception {
+ config.property("foo", "bar");
+ final EmptyFeature emptyFeature = new EmptyFeature();
+ config.register(emptyFeature);
+ config.register(ComplexEmptyProvider.class, ExceptionMapper.class);
+
+ final CommonConfig other = new CommonConfig(null, ComponentBag.INCLUDE_ALL);
+ other.property("foo", "baz");
+ other.register(UnconfigurableFeature.class);
+ other.register(ComplexEmptyProvider.class, ReaderInterceptor.class, ContainerRequestFilter.class);
+
+ assertEquals("baz", other.getProperty("foo"));
+ assertEquals(1, other.getProperties().size());
+ assertEquals(2, other.getClasses().size());
+ assertEquals(0, other.getInstances().size());
+ assertEquals(2, other.getContracts(ComplexEmptyProvider.class).size());
+ assertTrue(other.getContracts(ComplexEmptyProvider.class).containsKey(ReaderInterceptor.class));
+ assertTrue(other.getContracts(ComplexEmptyProvider.class).containsKey(ContainerRequestFilter.class));
+
+ other.loadFrom(config);
+
+ assertEquals("bar", other.getProperty("foo"));
+ assertEquals(1, other.getProperties().size());
+ assertEquals(1, other.getClasses().size());
+ assertEquals(1, other.getInstances().size());
+ assertEquals(1, other.getContracts(ComplexEmptyProvider.class).size());
+ assertSame(ExceptionMapper.class, other.getContracts(ComplexEmptyProvider.class).keySet().iterator().next());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testGetFeatures() throws Exception {
+ final EmptyFeature emptyFeature = new EmptyFeature();
+ final UnconfigurableFeature unconfigurableFeature = new UnconfigurableFeature();
+ final ComplexEmptyProviderFeature providerFeature = new ComplexEmptyProviderFeature();
+
+ config.register(emptyFeature);
+ config.register(unconfigurableFeature);
+ config.register(providerFeature, ReaderInterceptor.class);
+
+ assertFalse(config.getConfiguration().isEnabled(emptyFeature));
+ assertFalse(config.getConfiguration().isEnabled(unconfigurableFeature));
+ assertFalse(config.getConfiguration().isEnabled(providerFeature));
+
+ assertTrue(config.getConfiguration().isRegistered(emptyFeature));
+ assertTrue(config.getConfiguration().isRegistered(unconfigurableFeature));
+ assertTrue(config.getConfiguration().isRegistered(providerFeature));
+ }
+
+
+ @Test
+ // Regression test for JERSEY-1638.
+ public void testGetNonExistentProviderContractsASEmptyMap() throws Exception {
+ assertTrue(config.getConfiguration().getContracts(CommonConfigTest.class).isEmpty());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testGetClasses() throws Exception {
+ _testCollectionsCommon("GetProviderClasses", config.getClasses(), EmptyFeature.class);
+
+ config.register(ComplexEmptyProviderFeature.class,
+ WriterInterceptor.class, ReaderInterceptor.class, ContainerRequestFilter.class);
+ assertEquals(1, config.getClasses().size());
+
+ config.register(EmptyFeature.class);
+
+ final Set<Class<?>> providerClasses = config.getClasses();
+ assertEquals(2, providerClasses.size());
+ assertTrue(providerClasses.contains(ComplexEmptyProviderFeature.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testGetInstances() throws Exception {
+ _testCollectionsCommon("GetProviderInstances", config.getInstances(), new EmptyFeature());
+
+ final ComplexEmptyProviderFeature providerFeature1 = new ComplexEmptyProviderFeature();
+ config.register(providerFeature1, WriterInterceptor.class);
+ assertEquals(1, config.getInstances().size());
+ assertTrue(config.getInstances().contains(providerFeature1));
+
+ final EmptyFeature emptyFeature = new EmptyFeature();
+ config.register(emptyFeature);
+ assertEquals(2, config.getInstances().size());
+ assertTrue(config.getInstances().contains(emptyFeature));
+
+ final ComplexEmptyProviderFeature providerFeature2 = new ComplexEmptyProviderFeature();
+ config.register(providerFeature2, ReaderInterceptor.class, ContainerRequestFilter.class);
+ assertEquals(2, config.getInstances().size());
+ assertFalse(config.getInstances().contains(providerFeature2));
+ }
+
+ @Test
+ public void testRegisterClass() throws Exception {
+ try {
+ final Class clazz = null;
+ //noinspection ConstantConditions
+ config.register(clazz);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ for (int i = 0; i < 2; i++) {
+ config.register(ComplexEmptyProvider.class);
+ }
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size());
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+
+ assertTrue(config.isRegistered(ComplexEmptyProvider.class));
+ }
+
+ @Test
+ public void testRegisterInstance() throws Exception {
+ try {
+ config.register(null);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ final ComplexEmptyProvider[] ceps = new ComplexEmptyProvider[2];
+ for (int i = 0; i < 2; i++) {
+ ceps[i] = new ComplexEmptyProvider();
+ config.register(ceps[i]);
+ }
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size());
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+
+ assertTrue(config.isRegistered(ComplexEmptyProvider.class));
+ assertTrue(config.isRegistered(ceps[0]));
+ assertFalse(config.isRegistered(ceps[1]));
+ }
+
+ @Test
+ public void testRegisterClassInstanceClash() throws Exception {
+ final ComplexEmptyProvider complexEmptyProvider = new ComplexEmptyProvider();
+
+ config.register(ComplexEmptyProvider.class);
+ config.register(complexEmptyProvider);
+ config.register(ComplexEmptyProvider.class);
+
+ assertTrue(config.getClasses().contains(ComplexEmptyProvider.class));
+ assertFalse(config.getInstances().contains(complexEmptyProvider));
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size());
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+ }
+
+ @Test
+ public void testRegisterClassBingingPriority() throws Exception {
+ try {
+ final Class clazz = null;
+ //noinspection ConstantConditions
+ config.register(clazz, Priorities.USER);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ for (final int priority : new int[]{Priorities.USER, Priorities.AUTHENTICATION}) {
+ config.register(ComplexEmptyProvider.class, priority);
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size());
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+
+ // All priorities are the same.
+ assertEquals(Priorities.USER, contractProvider.getPriority(ReaderInterceptor.class));
+ assertEquals(Priorities.USER, contractProvider.getPriority(ContainerRequestFilter.class));
+ assertEquals(Priorities.USER, contractProvider.getPriority(ExceptionMapper.class));
+ }
+ }
+
+ @Test
+ public void testRegisterInstanceBingingPriority() throws Exception {
+ try {
+ config.register(null, Priorities.USER);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ final Class<ComplexEmptyProvider> providerClass = ComplexEmptyProvider.class;
+
+ for (final int priority : new int[]{Priorities.USER, Priorities.AUTHENTICATION}) {
+ config.register(providerClass, priority);
+
+ final CommonConfig commonConfig = config;
+ final ContractProvider contractProvider =
+ commonConfig.getComponentBag().getModel(providerClass);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size()); // Feature is not there.
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+
+ // All priorities are the same.
+ assertEquals(Priorities.USER, contractProvider.getPriority(ReaderInterceptor.class));
+ assertEquals(Priorities.USER, contractProvider.getPriority(ContainerRequestFilter.class));
+ assertEquals(Priorities.USER, contractProvider.getPriority(ExceptionMapper.class));
+ }
+ }
+
+ @Test
+ public void testRegisterClassInstanceBindingPriorityClash() throws Exception {
+ final ComplexEmptyProvider complexEmptyProvider = new ComplexEmptyProvider();
+
+ config.register(ComplexEmptyProvider.class, Priorities.AUTHENTICATION);
+ config.register(complexEmptyProvider, Priorities.USER);
+
+
+ assertTrue(config.getClasses().contains(ComplexEmptyProvider.class));
+ assertFalse(config.getInstances().contains(complexEmptyProvider));
+
+ final ComponentBag componentBag = config.getComponentBag();
+ final ContractProvider contractProvider =
+ componentBag.getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(3, contracts.size()); // Feature is not there.
+ assertTrue(contracts.contains(ReaderInterceptor.class));
+ assertTrue(contracts.contains(ContainerRequestFilter.class));
+ assertTrue(contracts.contains(ExceptionMapper.class));
+
+ // All priorities are the same.
+ assertEquals(Priorities.AUTHENTICATION, contractProvider.getPriority(ReaderInterceptor.class));
+ assertEquals(Priorities.AUTHENTICATION, contractProvider.getPriority(ContainerRequestFilter.class));
+ assertEquals(Priorities.AUTHENTICATION, contractProvider.getPriority(ExceptionMapper.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterClassContracts() throws Exception {
+ try {
+ final Class clazz = null;
+ //noinspection ConstantConditions
+ config.register(clazz, ReaderInterceptor.class);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ config.register(ComplexEmptyProvider.class,
+ ReaderInterceptor.class, ContainerRequestFilter.class, WriterInterceptor.class);
+ final ContractProvider contractProvider = config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+ assertEquals(2, contracts.size());
+ assertTrue(ReaderInterceptor.class + " is not registered.", contracts.contains(ReaderInterceptor.class));
+ assertTrue(ContainerRequestFilter.class + " is not registered.", contracts.contains(ContainerRequestFilter.class));
+ assertFalse(WriterInterceptor.class + " should not be registered.", contracts.contains(WriterInterceptor.class));
+
+ assertTrue(config.getInstances().isEmpty());
+ assertTrue(config.getClasses().contains(ComplexEmptyProvider.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterInstancesContracts() throws Exception {
+ try {
+ config.register(null, ReaderInterceptor.class);
+ fail("Cannot register null.");
+ } catch (final IllegalArgumentException e) {
+ // OK.
+ }
+
+ final ComplexEmptyProvider complexEmptyProvider = new ComplexEmptyProvider();
+ config.register(complexEmptyProvider,
+ ReaderInterceptor.class, ContainerRequestFilter.class, WriterInterceptor.class);
+ final ContractProvider contractProvider = config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+ assertEquals(2, contracts.size());
+ assertTrue(ReaderInterceptor.class + " is not registered.", contracts.contains(ReaderInterceptor.class));
+ assertTrue(ContainerRequestFilter.class + " is not registered.", contracts.contains(ContainerRequestFilter.class));
+ assertFalse(WriterInterceptor.class + " should not be registered.", contracts.contains(WriterInterceptor.class));
+
+ assertTrue(config.getInstances().contains(complexEmptyProvider));
+ assertTrue(config.getClasses().isEmpty());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterClassContractsFeatureNotInvoked() throws Exception {
+ config.register(ComplexEmptyProviderFeature.class, ReaderInterceptor.class);
+ assertFalse(config.getConfiguration().isEnabled(ComplexEmptyProviderFeature.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterInstancesContractsFeatureNotInvoked() throws Exception {
+ final ComplexEmptyProviderFeature feature = new ComplexEmptyProviderFeature();
+ config.register(feature, ReaderInterceptor.class);
+ assertFalse(config.getConfiguration().isEnabled(ComplexEmptyProviderFeature.class));
+ assertFalse(config.getConfiguration().isEnabled(feature));
+ }
+
+ @Test
+ public void testRegisterClassNullContracts() throws Exception {
+ config.register(ComplexEmptyProvider.class, (Class) null);
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(0, contracts.size());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterInstanceNullContracts() throws Exception {
+ config.register(new ComplexEmptyProvider(), (Class) null);
+
+ final ContractProvider contractProvider =
+ config.getComponentBag().getModel(ComplexEmptyProvider.class);
+ final Set<Class<?>> contracts = contractProvider.getContracts();
+
+ assertEquals(0, contracts.size());
+ }
+
+ // Reproducer JERSEY-1637
+ @Test
+ public void testRegisterNullOrEmptyContracts() {
+ final ComplexEmptyProvider provider = new ComplexEmptyProvider();
+
+ config.register(ComplexEmptyProvider.class, (Class<?>[]) null);
+ assertFalse(config.getConfiguration().isRegistered(ComplexEmptyProvider.class));
+
+ config.register(provider, (Class<?>[]) null);
+ assertFalse(config.getConfiguration().isRegistered(ComplexEmptyProvider.class));
+ assertFalse(config.getConfiguration().isRegistered(provider));
+
+ config.register(ComplexEmptyProvider.class, new Class[0]);
+ assertFalse(config.getConfiguration().isRegistered(ComplexEmptyProvider.class));
+
+ config.register(provider, new Class[0]);
+ assertFalse(config.getConfiguration().isRegistered(ComplexEmptyProvider.class));
+ assertFalse(config.getConfiguration().isRegistered(provider));
+ }
+
+ @Priority(300)
+ public static class LowPriorityProvider implements WriterInterceptor, ReaderInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ // Do nothing.
+ }
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return context.proceed();
+ }
+ }
+
+ @Priority(200)
+ public static class MidPriorityProvider implements WriterInterceptor, ReaderInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ // Do nothing.
+ }
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return context.proceed();
+ }
+ }
+
+ @Priority(100)
+ public static class HighPriorityProvider implements WriterInterceptor, ReaderInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ // Do nothing.
+ }
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return context.proceed();
+ }
+ }
+
+ @Test
+ public void testProviderOrderManual() throws Exception {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+
+ config.register(MidPriorityProvider.class, 500);
+ config.register(LowPriorityProvider.class, 20);
+ config.register(HighPriorityProvider.class, 150);
+
+ ProviderBinder.bindProviders(config.getComponentBag(), injectionManager);
+
+ injectionManager.completeRegistration();
+ final Iterable<WriterInterceptor> allProviders =
+ Providers.getAllProviders(injectionManager, WriterInterceptor.class, new RankedComparator<>());
+
+ final Iterator<WriterInterceptor> iterator = allProviders.iterator();
+
+ assertEquals(LowPriorityProvider.class, iterator.next().getClass());
+ assertEquals(HighPriorityProvider.class, iterator.next().getClass());
+ assertEquals(MidPriorityProvider.class, iterator.next().getClass());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void testProviderOrderSemiAutomatic() throws Exception {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+
+ config.register(MidPriorityProvider.class, 50);
+ config.register(LowPriorityProvider.class, 2000);
+ config.register(HighPriorityProvider.class);
+
+ ProviderBinder.bindProviders(config.getComponentBag(), injectionManager);
+ injectionManager.completeRegistration();
+ final Iterable<WriterInterceptor> allProviders =
+ Providers.getAllProviders(injectionManager, WriterInterceptor.class, new RankedComparator<>());
+
+ final Iterator<WriterInterceptor> iterator = allProviders.iterator();
+
+ assertEquals(MidPriorityProvider.class, iterator.next().getClass());
+ assertEquals(HighPriorityProvider.class, iterator.next().getClass());
+ assertEquals(LowPriorityProvider.class, iterator.next().getClass());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void testProviderOrderAutomatic() throws Exception {
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ config.register(MidPriorityProvider.class);
+ config.register(LowPriorityProvider.class);
+ config.register(HighPriorityProvider.class);
+
+ ProviderBinder.bindProviders(config.getComponentBag(), injectionManager);
+ injectionManager.completeRegistration();
+
+ final Iterable<WriterInterceptor> allProviders =
+ Providers.getAllProviders(injectionManager, WriterInterceptor.class, new RankedComparator<>());
+
+ final Iterator<WriterInterceptor> iterator = allProviders.iterator();
+
+ assertEquals(HighPriorityProvider.class, iterator.next().getClass());
+ assertEquals(MidPriorityProvider.class, iterator.next().getClass());
+ assertEquals(LowPriorityProvider.class, iterator.next().getClass());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testProviderOrderDifForContracts() throws Exception {
+ final Map<Class<?>, Integer> contracts = new IdentityHashMap<>();
+
+ contracts.put(WriterInterceptor.class, ContractProvider.NO_PRIORITY);
+ contracts.put(ReaderInterceptor.class, 2000);
+ config.register(MidPriorityProvider.class, contracts);
+ contracts.clear();
+
+ contracts.put(WriterInterceptor.class, ContractProvider.NO_PRIORITY);
+ contracts.put(ReaderInterceptor.class, 1000);
+ config.register(LowPriorityProvider.class, contracts);
+ contracts.clear();
+
+ contracts.put(WriterInterceptor.class, ContractProvider.NO_PRIORITY);
+ contracts.put(ReaderInterceptor.class, 3000);
+ config.register(HighPriorityProvider.class, contracts);
+ contracts.clear();
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ProviderBinder.bindProviders(config.getComponentBag(), injectionManager);
+
+ injectionManager.completeRegistration();
+ final Iterable<WriterInterceptor> writerInterceptors =
+ Providers.getAllProviders(injectionManager, WriterInterceptor.class, new RankedComparator<>());
+
+ final Iterator<WriterInterceptor> writerIterator = writerInterceptors.iterator();
+
+ assertEquals(HighPriorityProvider.class, writerIterator.next().getClass());
+ assertEquals(MidPriorityProvider.class, writerIterator.next().getClass());
+ assertEquals(LowPriorityProvider.class, writerIterator.next().getClass());
+ assertFalse(writerIterator.hasNext());
+
+ final Iterable<ReaderInterceptor> readerInterceptors =
+ Providers.getAllProviders(injectionManager, ReaderInterceptor.class, new RankedComparator<>());
+
+ final Iterator<ReaderInterceptor> readerIterator = readerInterceptors.iterator();
+
+ assertEquals(LowPriorityProvider.class, readerIterator.next().getClass());
+ assertEquals(MidPriorityProvider.class, readerIterator.next().getClass());
+ assertEquals(HighPriorityProvider.class, readerIterator.next().getClass());
+ assertFalse(readerIterator.hasNext());
+ }
+
+
+ private <T> void _testCollectionsCommon(final String testName, final Collection<T> collection, final T element)
+ throws Exception {
+
+ // Not null.
+ assertNotNull(testName + " - returned collection is null.", collection);
+
+ // Immutability.
+ try {
+ collection.add(element);
+ fail(testName + " - returned collection should be immutable.");
+ } catch (final Exception e) {
+ // OK.
+ }
+ }
+
+ public static final class CustomReaderA implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return null;
+ }
+ }
+
+ public static final class CustomReaderB implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ return null;
+ }
+ }
+
+ public static final class SimpleFeatureA implements Feature {
+
+ private boolean initB;
+
+ public SimpleFeatureA() {
+ }
+
+ public SimpleFeatureA(final boolean initB) {
+ this.initB = initB;
+ }
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(initB ? CustomReaderB.class : CustomReaderA.class);
+ return true;
+ }
+ }
+
+ public static final class SimpleFeatureB implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(CustomReaderB.class);
+ return true;
+ }
+ }
+
+ public static final class InstanceFeatureA implements Feature {
+
+ private boolean initB;
+
+ public InstanceFeatureA() {
+ }
+
+ public InstanceFeatureA(final boolean initB) {
+ this.initB = initB;
+ }
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(initB ? new CustomReaderB() : new CustomReaderA());
+ return true;
+ }
+ }
+
+ public static final class ComplexFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(SimpleFeatureA.class);
+ config.register(SimpleFeatureB.class);
+ return true;
+ }
+ }
+
+ public static final class RecursiveFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(new CustomReaderA());
+ config.register(RecursiveFeature.class);
+ return true;
+ }
+ }
+
+ public static final class RecursiveInstanceFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext config) {
+ config.register(new CustomReaderA());
+ config.register(new RecursiveInstanceFeature());
+ return true;
+ }
+ }
+
+ @Test
+ public void testConfigureFeatureHierarchy() throws Exception {
+ config.register(ComplexFeature.class);
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertTrue(config.getConfiguration().isEnabled(ComplexFeature.class));
+
+ assertTrue(config.getConfiguration().isRegistered(CustomReaderA.class));
+ assertTrue(config.getConfiguration().isRegistered(CustomReaderB.class));
+ }
+
+ @Test
+ public void testConfigureFeatureRecursive() throws Exception {
+ config.register(RecursiveFeature.class);
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertTrue(config.getConfiguration().isEnabled(RecursiveFeature.class));
+ assertEquals(1, config.getInstances().size());
+ assertSame(CustomReaderA.class, config.getInstances().iterator().next().getClass());
+ }
+
+ @Test
+ public void testConfigureFeatureInstances() throws Exception {
+ final SimpleFeatureA f1 = new SimpleFeatureA();
+ config.register(f1);
+ final SimpleFeatureA f2 = new SimpleFeatureA(true);
+ config.register(f2);
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertTrue(config.getConfiguration().isEnabled(f1));
+ assertFalse(config.getConfiguration().isEnabled(f2));
+
+ assertTrue(config.getConfiguration().isRegistered(CustomReaderA.class));
+ assertFalse(config.getConfiguration().isRegistered(CustomReaderB.class));
+ }
+
+ @Test
+ public void testConfigureFeatureInstancesProviderInstances() throws Exception {
+ final InstanceFeatureA f1 = new InstanceFeatureA();
+ config.register(f1);
+ final InstanceFeatureA f2 = new InstanceFeatureA(true);
+ config.register(f2);
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertTrue(config.getConfiguration().isEnabled(f1));
+ assertFalse(config.getConfiguration().isEnabled(f2));
+
+ final Set<Object> providerInstances = config.getInstances();
+ assertEquals(2, providerInstances.size());
+
+ final Set<Object> pureProviderInstances =
+ config.getComponentBag().getInstances(ComponentBag.excludeMetaProviders(injectionManager));
+ assertEquals(1, pureProviderInstances.size());
+
+ int a = 0;
+ int b = 0;
+ for (final Object instance : pureProviderInstances) {
+ if (instance instanceof CustomReaderA) {
+ a++;
+ } else {
+ b++;
+ }
+ }
+ assertEquals(1, a);
+ assertEquals(0, b);
+ }
+
+ @Test
+ public void testConfigureFeatureInstanceRecursive() throws Exception {
+ config.register(new RecursiveInstanceFeature());
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+ assertEquals(0, config.getClasses().size());
+ assertEquals(2, config.getInstances().size());
+ final Set<Object> pureProviders =
+ config.getComponentBag().getInstances(ComponentBag.excludeMetaProviders(injectionManager));
+ assertEquals(1, pureProviders.size());
+ assertSame(CustomReaderA.class, pureProviders.iterator().next().getClass());
+ }
+
+ public static interface Contract {
+ }
+
+ public static class Service implements Contract {
+ }
+
+ public static class ContractBinder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(Service.class).to(Contract.class);
+ }
+ }
+
+ public static class ContractBinderFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(new ContractBinder());
+ return true;
+ }
+ }
+
+ @Test
+ public void testBinderConfiguringFeature() throws Exception {
+ config.register(ContractBinderFeature.class);
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+ injectionManager.completeRegistration();
+
+ assertTrue(config.isEnabled(ContractBinderFeature.class));
+ assertEquals(1, config.getInstances().size());
+ assertSame(ContractBinder.class, config.getInstances().iterator().next().getClass());
+
+ final Contract service = injectionManager.getInstance(Contract.class);
+ assertNotNull(service);
+ assertSame(Service.class, service.getClass());
+ }
+
+ public static class InjectMe {
+ }
+
+ public static class InjectIntoFeatureInstance implements Feature {
+
+ @Inject
+ private InjectMe injectMe;
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.property("instance-injected", injectMe != null);
+ return true;
+ }
+ }
+
+ public static class InjectIntoFeatureClass implements Feature {
+
+ @Inject
+ private InjectMe injectMe;
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.property("class-injected", injectMe != null);
+ return true;
+ }
+ }
+
+ public static class BindInjectMeInFeature implements Feature {
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new InjectMe());
+ }
+ });
+ return true;
+ }
+ }
+
+ @Test
+ public void testFeatureInjections() throws Exception {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+
+ config.register(InjectIntoFeatureClass.class)
+ .register(new InjectIntoFeatureInstance())
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new InjectMe());
+ }
+ });
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertThat("Feature instance not injected", config.getProperty("instance-injected").toString(), is("true"));
+ assertThat("Feature class not injected", config.getProperty("class-injected").toString(), is("true"));
+ }
+
+ @Test
+ @Ignore
+ public void testFeatureInjectionsBindInFeature() throws Exception {
+ config.register(new BindInjectMeInFeature());
+ config.register(InjectIntoFeatureClass.class);
+ config.register(new InjectIntoFeatureInstance());
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ ManagedObjectsFinalizer finalizer = new ManagedObjectsFinalizer(injectionManager);
+ config.configureMetaProviders(injectionManager, finalizer);
+
+ assertThat("Feature instance not injected", config.getProperty("instance-injected").toString(), is("true"));
+ assertThat("Feature class not injected", config.getProperty("class-injected").toString(), is("true"));
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java
new file mode 100644
index 0000000..1cfd53e
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.process.internal;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Qualifier;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.util.Producer;
+import org.glassfish.jersey.process.internal.ExecutorProviders;
+import org.glassfish.jersey.spi.ExecutorServiceProvider;
+import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
+import org.glassfish.jersey.spi.ScheduledThreadPoolExecutorProvider;
+import org.glassfish.jersey.spi.ThreadPoolExecutorProvider;
+
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * ExecutorProviders unit tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ExecutorProvidersTest extends AbstractBinder {
+
+ /**
+ * Custom scheduler injection qualifier.
+ */
+ @Qualifier
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface CustomScheduler {
+
+ }
+
+ /**
+ * Custom scheduler provider.
+ */
+ @CustomScheduler
+ public static class CustomSchedulerProvider extends ScheduledThreadPoolExecutorProvider {
+
+ /**
+ * Create a new instance of the scheduled thread pool executor provider.
+ */
+ public CustomSchedulerProvider() {
+ super("custom-scheduler");
+ }
+ }
+
+ /**
+ * Custom named scheduler provider.
+ */
+ @Named("custom-scheduler")
+ public static class CustomNamedSchedulerProvider extends ScheduledThreadPoolExecutorProvider {
+
+ /**
+ * Create a new instance of the scheduled thread pool executor provider.
+ */
+ public CustomNamedSchedulerProvider() {
+ super("custom-named-scheduler");
+ }
+ }
+
+ /**
+ * Custom executor injection qualifier.
+ */
+ @Qualifier
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface CustomExecutor {
+
+ }
+
+ /**
+ * Custom executor provider.
+ */
+ @CustomExecutor
+ public static class CustomExecutorProvider extends ThreadPoolExecutorProvider {
+
+ /**
+ * Create a new instance of the thread pool executor provider.
+ */
+ public CustomExecutorProvider() {
+ super("custom-executor");
+ }
+ }
+
+ /**
+ * Custom named executor provider.
+ */
+ @Named("custom-executor")
+ public static class CustomNamedExecutorProvider extends ThreadPoolExecutorProvider {
+
+ /**
+ * Create a new instance of the thread pool executor provider.
+ */
+ public CustomNamedExecutorProvider() {
+ super("custom-named-executor");
+ }
+ }
+
+ /**
+ * A task to retrieve the current thread name.
+ */
+ public static class CurrentThreadNameRetrieverTask implements Producer<String> {
+
+ @Override
+ public String call() {
+ return Thread.currentThread().getName();
+ }
+ }
+
+ /**
+ * Notifier of pre-destroy method invocation.
+ */
+ public static class PreDestroyNotifier {
+
+ private final CountDownLatch latch = new CountDownLatch(1);
+
+ @PreDestroy
+ public void preDestroy() {
+ latch.countDown();
+ }
+
+ public boolean await(final long timeout, final TimeUnit unit) throws InterruptedException {
+ return latch.await(timeout, unit);
+ }
+ }
+
+ /**
+ * Injectable executor client class.
+ */
+ public static class InjectedExecutorClient {
+
+ @Inject
+ private PreDestroyNotifier preDestroyNotifier;
+
+ @Inject
+ @CustomExecutor
+ private ExecutorService customExecutor;
+
+ @Inject
+ @Named("custom-executor")
+ private ExecutorService customNamedExecutor;
+
+ @Inject
+ @CustomScheduler
+ private ScheduledExecutorService customScheduler;
+
+ @Inject
+ @CustomScheduler
+ private ExecutorService customSchedulerAsExecutor;
+
+ @Inject
+ @Named("custom-scheduler")
+ private ScheduledExecutorService customNamedScheduler;
+
+ @Inject
+ @Named("custom-scheduler")
+ private ScheduledExecutorService customNamedSchedulerAsExecutor;
+
+ }
+
+ private InjectionManager injectionManager;
+
+ @Override
+ protected void configure() {
+
+
+
+ bind(CustomExecutorProvider.class).to(ExecutorServiceProvider.class).in(Singleton.class);
+ bind(CustomNamedExecutorProvider.class).to(ExecutorServiceProvider.class).in(Singleton.class);
+ bind(CustomSchedulerProvider.class).to(ScheduledExecutorServiceProvider.class).in(Singleton.class);
+ bind(CustomNamedSchedulerProvider.class).to(ScheduledExecutorServiceProvider.class).in(Singleton.class);
+ bindAsContract(PreDestroyNotifier.class).in(Singleton.class);
+ }
+
+ /**
+ * Set-up the tests.
+ */
+ @Before
+ public void setup() {
+ injectionManager = Injections.createInjectionManager(this);
+ ExecutorProviders.registerExecutorBindings(injectionManager);
+ injectionManager.completeRegistration();
+ }
+
+ /**
+ * Test executor and scheduler injection as well as the proper shutdown when injection manager is closed.
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testExecutorInjectionAndReleasing() throws Exception {
+ final InjectedExecutorClient executorClient = Injections.getOrCreate(injectionManager, InjectedExecutorClient.class);
+
+ assertThat(executorClient.customExecutor, Matchers.notNullValue());
+ assertThat(executorClient.customNamedExecutor, Matchers.notNullValue());
+
+ assertThat(executorClient.customScheduler, Matchers.notNullValue());
+ assertThat(executorClient.customNamedScheduler, Matchers.notNullValue());
+ assertThat(executorClient.customSchedulerAsExecutor, Matchers.notNullValue());
+ assertThat(executorClient.customNamedSchedulerAsExecutor, Matchers.notNullValue());
+
+ CurrentThreadNameRetrieverTask nameRetrieverTask = new CurrentThreadNameRetrieverTask();
+
+ // Test authenticity of injected executors
+ assertThat(executorClient.customExecutor.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-executor-"));
+ assertThat(executorClient.customNamedExecutor.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-named-executor-"));
+
+ // Test authenticity of injected schedulers
+ assertThat(executorClient.customScheduler.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-scheduler-"));
+ assertThat(executorClient.customNamedScheduler.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-named-scheduler-"));
+ assertThat(executorClient.customSchedulerAsExecutor.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-scheduler-"));
+ assertThat(executorClient.customNamedSchedulerAsExecutor.submit(nameRetrieverTask).get(),
+ Matchers.startsWith("custom-named-scheduler-"));
+
+ // Test proper executor shutdown when locator is shut down.
+ injectionManager.shutdown();
+
+ assertThat("Waiting for pre-destroy timed out.",
+ executorClient.preDestroyNotifier.await(3, TimeUnit.SECONDS), Matchers.is(true));
+
+ testShutDown("customExecutor", executorClient.customExecutor);
+ testShutDown("customNamedExecutor", executorClient.customNamedExecutor);
+ testShutDown("customScheduler", executorClient.customScheduler);
+ testShutDown("customNamedScheduler", executorClient.customNamedScheduler);
+ testShutDown("customSchedulerAsExecutor", executorClient.customSchedulerAsExecutor);
+ testShutDown("customNamedSchedulerAsExecutor", executorClient.customNamedSchedulerAsExecutor);
+ }
+
+ private void testShutDown(String name, ExecutorService executorService) throws InterruptedException {
+ assertTrue(name + " not shutdown", executorService.isShutdown());
+ assertTrue(name + " not terminated", executorService.isTerminated());
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/RequestScopeTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/RequestScopeTest.java
new file mode 100644
index 0000000..36a23e9
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/RequestScopeTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.process.internal;
+
+import java.lang.reflect.Type;
+
+import org.glassfish.jersey.inject.hk2.Hk2RequestScope;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.process.internal.RequestScope;
+
+import org.glassfish.hk2.api.ServiceHandle;
+import org.glassfish.hk2.utilities.AbstractActiveDescriptor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test of the {@link RequestScope request scope}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class RequestScopeTest {
+
+ @Test
+ public void testScopeWithCreatedInstance() {
+ final RequestScope requestScope = new Hk2RequestScope();
+ assertNull(requestScope.suspendCurrent());
+ final Hk2RequestScope.Instance context = (Hk2RequestScope.Instance) requestScope.createContext();
+ ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
+ context.put(inhab, "1");
+ requestScope.runInScope(context, () -> {
+ assertEquals("1", context.get(inhab));
+ context.release();
+ assertEquals("1", context.get(inhab));
+ });
+ assertNull(context.get(inhab));
+ }
+
+ @Test
+ public void testScopeReleaseInsideScope() {
+ final RequestScope requestScope = new Hk2RequestScope();
+ assertNull(requestScope.suspendCurrent());
+ final Hk2RequestScope.Instance instance = (Hk2RequestScope.Instance) requestScope.createContext();
+ ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
+ instance.put(inhab, "1");
+ requestScope.runInScope(instance, () -> {
+ final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
+ assertEquals(internalInstance, instance);
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertEquals("1", instance.get(inhab));
+ });
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertNull(instance.get(inhab));
+ }
+
+ @Test
+ public void testScopeWithImplicitInstance() throws Exception {
+ final RequestScope requestScope = new Hk2RequestScope();
+ assertNull(requestScope.suspendCurrent());
+ ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
+ final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
+ final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
+ assertNull(internalInstance.get(inhab));
+ internalInstance.put(inhab, "1");
+ assertEquals("1", internalInstance.get(inhab));
+ return internalInstance;
+ });
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertNull(instance.get(inhab));
+ }
+
+ @Test
+ public void testScopeWithTwoInternalTasks() throws Exception {
+ final RequestScope requestScope = new Hk2RequestScope();
+ assertNull(requestScope.suspendCurrent());
+ ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
+ final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
+ final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
+
+ final Hk2RequestScope.Instance anotherInstance = requestScope.runInScope(() -> {
+ final Hk2RequestScope.Instance currentInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
+ assertTrue(!currentInstance.equals(internalInstance));
+ currentInstance.put(inhab, "1");
+ return currentInstance;
+ });
+ assertTrue(!anotherInstance.equals(internalInstance));
+ assertEquals("1", anotherInstance.get(inhab));
+ anotherInstance.release();
+ assertNull(anotherInstance.get(inhab));
+
+ return internalInstance;
+ });
+ instance.release();
+ assertNull(instance.get(inhab));
+ }
+
+ @Test
+ public void testMultipleGetInstanceCalls() throws Exception {
+ final RequestScope requestScope = new Hk2RequestScope();
+ assertNull(requestScope.suspendCurrent());
+ ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
+ final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
+ final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
+ internalInstance.put(inhab, "1");
+ requestScope.suspendCurrent();
+ requestScope.suspendCurrent();
+ requestScope.suspendCurrent();
+ requestScope.suspendCurrent();
+ return internalInstance;
+ });
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertEquals("1", instance.get(inhab));
+ instance.release();
+ assertNull(instance.get(inhab));
+ }
+
+ /**
+ * Test request scope inhabitant.
+ */
+ public static class TestProvider extends AbstractActiveDescriptor<String> {
+
+ private final String id;
+
+ public TestProvider(final String id) {
+ super();
+ this.id = id;
+ }
+
+ @Override
+ public Class<?> getImplementationClass() {
+ return String.class;
+ }
+
+ @Override
+ public Type getImplementationType() {
+ return getImplementationClass();
+ }
+
+ @Override
+ public String create(final ServiceHandle<?> root) {
+ return id;
+ }
+ }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/uri/internal/JerseyUriBuilderTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/uri/internal/JerseyUriBuilderTest.java
new file mode 100644
index 0000000..7583010
--- /dev/null
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/uri/internal/JerseyUriBuilderTest.java
@@ -0,0 +1,1631 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common.uri.internal;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.uri.UriComponent;
+import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Uri builder implementation test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @author Martin Matula
+ * @author Miroslav Fuksa
+ * @author Paul Sandoz
+ * @author Vetle Leinonen-Roeim (vetle at roeim.net)
+ */
+public class JerseyUriBuilderTest {
+
+ public JerseyUriBuilderTest() {
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldKeepTrailingSlash() throws MalformedURLException, URISyntaxException {
+ final URL url = new URL("http://example.com/authentications;email=joe@joe.com/");
+ final UriBuilder builder = UriBuilder.fromPath(url.getPath()).replaceMatrix(null);
+
+ final URI result = builder.build();
+ assertEquals("/authentications/", result.toString());
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldRemoveAllIncludingSemicolon() throws MalformedURLException, URISyntaxException {
+ final URL url = new URL("http://example.com/authentications;email=joe@joe.com");
+ final UriBuilder builder = UriBuilder.fromPath(url.getPath()).replaceMatrix(null);
+
+ final URI result = builder.build();
+ assertEquals("/authentications", result.toString());
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldLeaveURIUntouched() {
+ final UriBuilder builder = UriBuilder.fromPath("/apples;order=random;color=blue/2006").replaceMatrix(null);
+ final URI result = builder.build();
+ assertEquals("/apples;order=random;color=blue/2006", result.toString());
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldLeaveURIUntouchedAndKeepSlash() {
+ final UriBuilder builder = UriBuilder.fromPath("/apples;order=random;color=blue/2006/").replaceMatrix(null);
+ final URI result = builder.build();
+ assertEquals("/apples;order=random;color=blue/2006/", result.toString());
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldOnlyRemoveMatrixInFinalSegment() {
+ final UriBuilder builder = UriBuilder.fromPath("/apples;order=random;color=blue/2006/bar;zot=baz").replaceMatrix(null);
+ final URI result = builder.build();
+ assertEquals("/apples;order=random;color=blue/2006/bar", result.toString());
+ }
+
+ // Reproducer for JERSEY-2537
+ @Test
+ public void shouldOnlyRemoveMatrixInFinalSegmentAndKeepSlash() {
+ final UriBuilder builder = UriBuilder.fromPath("/apples;order=random;color=blue/2006/bar;zot=baz/").replaceMatrix(null);
+ final URI result = builder.build();
+ assertEquals("/apples;order=random;color=blue/2006/bar/", result.toString());
+ }
+
+ // Reproducer for JERSEY-2036
+ @Test
+ public void testReplaceNonAsciiQueryParam() throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+ final URL url = new URL("http://example.com/getMyName?néme=t");
+ final String query = url.getQuery();
+
+ final UriBuilder builder = UriBuilder.fromPath(url.getPath()).scheme(url.getProtocol()).host(url.getHost())
+ .port(url.getPort())
+ .replaceQuery(query).fragment(url.getRef());
+
+ // Replace QueryParam.
+ final String parmName = "néme";
+ final String value = "value";
+
+ builder.replaceQueryParam(parmName, value);
+
+ final URI result = builder.build();
+ final URI expected = new URI("http://example.com/getMyName?néme=value");
+ assertEquals(expected.toASCIIString(), result.toASCIIString());
+ }
+
+ @Test
+ // See JAX_RS_SPEC-245
+ public void testReplacingUserInfo() {
+ final String userInfo = "foo:foo";
+
+ URI uri;
+ uri = UriBuilder.fromUri("http://foo2:foo2@localhost:8080").userInfo(userInfo).build();
+ assertEquals(userInfo, uri.getRawUserInfo());
+
+ uri = UriBuilder.fromUri("http://localhost:8080").userInfo(userInfo).build();
+ assertEquals(userInfo, uri.getRawUserInfo());
+ }
+
+ // Reproducer for JERSEY-1800
+ @Test
+ public void testEmptyUriString() throws URISyntaxException {
+ final URI uri = URI.create("");
+ JerseyUriBuilder ub = new JerseyUriBuilder().uri("news:comp.lang.java").uri(uri);
+ assertEquals("news:", ub.toTemplate());
+ // note that even though the URI is valid according to RFC 3986,
+ // it is not possible to create a java.net.URI from this builder if SSP is empty
+
+ ub = new JerseyUriBuilder().uri("news:comp.lang.java").uri("");
+ assertEquals("news:", ub.toTemplate());
+ // note that even though the URI is valid according to RFC 3986,
+ // it is not possible to create a java.net.URI from this builder if SSP is empty
+ }
+
+ // Reproducer for JERSEY-2753
+ @Test
+ public void testUriBuilderShouldLeaveRelativePathRelative() {
+ final UriBuilder builder = JerseyUriBuilder.fromPath("");
+ builder.scheme("http");
+ builder.replacePath("path");
+
+ assertEquals("http:path", builder.build().toString());
+ }
+
+ @Test
+ public void testToTemplate() throws URISyntaxException {
+ final JerseyUriBuilder ub = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("{T1}")
+ .path("{T2}").segment("{T3}").queryParam("a", "{T4}", "v1")
+ .queryParam("b", "v2");
+ assertEquals("http://{T1}@examples.jersey.java.net/{T2}/{T3}?a={T4}&a=v1&b=v2", ub.toTemplate());
+
+ ub.queryParam("a", "v3").queryParam("c", "v4");
+ assertEquals("http://{T1}@examples.jersey.java.net/{T2}/{T3}?a={T4}&a=v1&b=v2&a=v3&c=v4", ub.toTemplate());
+ }
+
+ @Test
+ public void testPathTemplateValueEncoding() throws URISyntaxException {
+ String result;
+ result = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("a/b").path("a/b")
+ .segment("a/b").build().toString();
+ assertEquals("http://a%2Fb@examples.jersey.java.net/a/b/a%2Fb", result);
+
+ result = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("{T1}").path("{T2}")
+ .segment("{T3}").build("a/b", "a/b", "a/b").toString();
+ assertEquals("http://a%2Fb@examples.jersey.java.net/a%2Fb/a%2Fb", result);
+
+ result = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("{T1}").path("{T2}")
+ .segment("{T3}").build(new Object[] {"a/b", "a/b", "a/b"}, false).toString();
+ assertEquals("http://a%2Fb@examples.jersey.java.net/a/b/a/b", result);
+
+ result = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("{T1}").path("{T2}")
+ .segment("{T2}").build("a@b", "a@b").toString();
+ assertEquals("http://a%40b@examples.jersey.java.net/a@b/a@b", result);
+
+ result = new JerseyUriBuilder().uri(new URI("http://examples.jersey.java.net/")).userInfo("{T}").path("{T}")
+ .segment("{T}").build("a@b").toString();
+ assertEquals("http://a%40b@examples.jersey.java.net/a@b/a@b", result);
+ }
+
+ @Test
+ public void testReplaceMatrixParamWithNull() {
+ final UriBuilder builder = new JerseyUriBuilder().matrixParam("matrix", "param1", "param2");
+ builder.replaceMatrixParam("matrix", (Object[]) null);
+ assertEquals(builder.build().toString(), "");
+ }
+
+ // for completeness (added along with regression tests for JERSEY-1114)
+ @Test
+ public void testBuildNoSlashUri() {
+ final UriBuilder builder = new JerseyUriBuilder().uri(URI.create("http://localhost:8080")).path("test");
+ assertEquals("http://localhost:8080/test", builder.build().toString());
+ }
+
+ // regression test for JERSEY-1114
+ @Test
+ public void testBuildFromMapNoSlashInUri() {
+ final UriBuilder builder = new JerseyUriBuilder().uri(URI.create("http://localhost:8080")).path("test");
+ assertEquals("http://localhost:8080/test", builder.buildFromMap(new HashMap<String, Object>()).toString());
+ }
+
+ // regression test for JERSEY-1114
+ @Test
+ public void testBuildFromArrayNoSlashInUri() {
+ final UriBuilder builder = new JerseyUriBuilder().uri(URI.create("http://localhost:8080")).path("test");
+ assertEquals("http://localhost:8080/test", builder.build("testing").toString());
+ }
+
+ @Test
+ public void testReplaceNullMatrixParam() {
+ try {
+ new JerseyUriBuilder().replaceMatrixParam(null, "param");
+ } catch (final IllegalArgumentException e) {
+ return;
+ } catch (final Exception e) {
+ fail("Expected IllegalArgumentException but got " + e.toString());
+ }
+ fail("Expected IllegalArgumentException but no exception was thrown.");
+ }
+
+ // regression test for JERSEY-1081
+ @Test
+ public void testReplaceQueryParam() {
+ final URI uri = new JerseyUriBuilder().path("http://localhost/").replaceQueryParam("foo", "test").build();
+ assertEquals("http://localhost/?foo=test", uri.toString());
+ }
+
+ // regression test for JERSEY-1081
+ @Test
+ public void testReplaceQueryParamAndClone() {
+ final URI uri = new JerseyUriBuilder().path("http://localhost/").replaceQueryParam("foo", "test").clone().build();
+ assertEquals("http://localhost/?foo=test", uri.toString());
+ }
+
+ // regression test for JERSEY-1341
+ @Test
+ public void testEmptyQueryParamValue() {
+ final URI uri = new JerseyUriBuilder().path("http://localhost/").queryParam("test", "").build();
+ assertEquals("http://localhost/?test=", uri.toString());
+ }
+
+ // regression test for JERSEY-1457
+ @Test
+ public void testChangeSspViaStringUriTemplate() throws Exception {
+ final String[] origUris = new String[] {"news:comp.lang.java", "tel:+1-816-555-1212"};
+ final URI[] replaceUris = new URI[] {new URI(null, "news.lang.java", null), new URI(null, "+1-866-555-1212", null)};
+ final String[] results = new String[] {"news:news.lang.java", "tel:+1-866-555-1212"};
+ int i = 0;
+ while (i < origUris.length) {
+ assertEquals(results[i],
+ UriBuilder.fromUri(new URI(origUris[i])).uri(replaceUris[i].toASCIIString()).build().toString());
+ i++;
+ }
+ }
+
+ @Test
+ public void testChangeUriStringAfterChangingOpaqueSchemeToHttp() {
+ assertEquals("http://www.example.org/test",
+ UriBuilder.fromUri("tel:+1-816-555-1212").scheme("http").uri("//www.{host}.org").path("test").build("example")
+ .toString());
+ }
+
+ @Test
+ public void testUriBuilderTemplatesSimple() {
+ testUri("a:/path");
+ testUri("a:/p");
+ testUri("a:/path/x/y/z");
+ testUri("a:/path/x?q=12#fragment");
+ testUri("a:/p?q#f");
+ testUri("a://host");
+ testUri("a://host:5555/a/b");
+ testUri("a://h:5/a/b");
+ testUri("a:/user@host:12345"); //user@host:12345 is not authority but path
+ testUri("a:/user@host:12345/a/b/c");
+ testUri("a:/user@host:12345/a/b/c?aaa&bbb#ccc");
+ testUri("a:/user@host.hhh.ddd.c:12345/a/b/c?aaa&bbb#ccc");
+ testUri("/a");
+ testUri("/a/../../b/c/d");
+ testUri("//localhost:80/a/b");
+ testUri("//l:8/a/b");
+ testUri("a/b");
+ testUri("a");
+ testUri("../../s");
+ testUri("mailto:test@test.com");
+ testUri("http://orac@le:co@m:1234/a/b/ccc?a#fr");
+ testUri("http://[::FFFF:129.144.52.38]:1234/a/b/ccc?a#fr");
+ testUri("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:1234/a/b/ccc?a#fr");
+
+ }
+
+ @Test
+ @Ignore
+ public void failingTests() {
+ testUri("a://#fragment"); // fails in JerseyUriBuilder
+ testUri("a://?query");
+
+ // fails: opaque uris are not supported by UriTemplate
+ final URI uri = new JerseyUriBuilder().uri("{scheme}://{mailto}").build("mailto", "email@test.ttt");
+ assertEquals("mailto:email@test.ttt", uri.toString());
+ }
+
+ @Test
+ public void testUriBuilderTemplates() {
+ URI uri = new JerseyUriBuilder().uri("http://localhost:8080/{path}").build("a/b/c");
+ assertEquals("http://localhost:8080/a%2Fb%2Fc", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}").build("http", "localhost");
+ assertEquals("http://localhost", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("http://{host}:8080/{path}").build("l", "a/b/c");
+ assertEquals("http://l:8080/a%2Fb%2Fc", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}:{port}/{path}").build("s", "h", new Integer(1), "a");
+ assertEquals("s://h:1/a", uri.toString());
+
+ final Map<String, Object> values = new HashMap<String, Object>();
+ values.put("scheme", "s");
+ values.put("host", "h");
+ values.put("port", 1);
+ values.put("path", "p/p");
+ values.put("query", "q");
+ values.put("fragment", "f");
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}:{port}/{path}?{query}#{fragment}").buildFromMap(values);
+ assertEquals("s://h:1/p%2Fp?q#f", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}:{port}/{path}/{path2}").build("s", "h", new Integer(1), "a", "b");
+ assertEquals("s://h:1/a/b", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}:{port}/{path}/{path2}").build("s", "h", new Integer(1), "a", "b");
+ assertEquals("s://h:1/a/b", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("//{host}:{port}/{path}/{path2}").build("h", new Integer(1), "a", "b");
+ assertEquals("//h:1/a/b", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("/{a}/{a}/{b}").build("a", "b");
+ assertEquals("/a/a/b", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("/{a}/{a}/{b}?{queryParam}").build("a", "b", "query");
+ assertEquals("/a/a/b?query", uri.toString());
+
+ // partial templates
+ uri = new JerseyUriBuilder().uri("/{a}xx/{a}/{b}?{queryParam}").build("a", "b", "query");
+ assertEquals("/axx/a/b?query", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("my{scheme}://my{host}:1{port}/my{path}/my{path2}")
+ .build("s", "h", new Integer(1), "a", "b/c");
+ assertEquals("mys://myh:11/mya/myb%2Fc", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("my{scheme}post://my{host}post:5{port}9/my{path}post/my{path2}post")
+ .build("s", "h", new Integer(1), "a", "b");
+ assertEquals("myspost://myhpost:519/myapost/mybpost", uri.toString());
+ }
+
+ @Test
+ public void testUriBuilderTemplatesNotEncodedSlash() {
+ URI uri = new JerseyUriBuilder().uri("http://localhost:8080/{path}").build(new Object[] {"a/b/c"}, false);
+ assertEquals("http://localhost:8080/a/b/c", uri.toString());
+
+ uri = new JerseyUriBuilder().uri("http://{host}:8080/{path}").build(new Object[] {"l", "a/b/c"}, false);
+ assertEquals("http://l:8080/a/b/c", uri.toString());
+
+ final Map<String, Object> values = new HashMap<String, Object>();
+ values.put("scheme", "s");
+ values.put("host", "h");
+ values.put("port", 1);
+ values.put("path", "p/p");
+ values.put("query", "q");
+ values.put("fragment", "f");
+
+ uri = new JerseyUriBuilder().uri("{scheme}://{host}:{port}/{path}?{query}#{fragment}").buildFromMap(values, false);
+ assertEquals("s://h:1/p/p?q#f", uri.toString());
+ }
+
+ private void testUri(final String input) {
+ final URI uri = new JerseyUriBuilder().uri(input).clone().build();
+
+ final URI originalUri = URI.create(input);
+ assertEquals(originalUri.getScheme(), uri.getScheme());
+ assertEquals(originalUri.getHost(), uri.getHost());
+ assertEquals(originalUri.getPort(), uri.getPort());
+ assertEquals(originalUri.getUserInfo(), uri.getUserInfo());
+ assertEquals(originalUri.getPath(), uri.getPath());
+ assertEquals(originalUri.getQuery(), uri.getQuery());
+ assertEquals(originalUri.getFragment(), uri.getFragment());
+ assertEquals(originalUri.getRawSchemeSpecificPart(), uri.getRawSchemeSpecificPart());
+ assertEquals(originalUri.isAbsolute(), uri.isAbsolute());
+ assertEquals(input, uri.toString());
+ }
+
+ @org.junit.Test
+ public void testOpaqueUri() {
+ final URI uri = UriBuilder.fromUri("mailto:a@b").build();
+ Assert.assertEquals("mailto:a@b", uri.toString());
+ }
+
+ @Test
+ public void testOpaqueUriReplaceSchemeSpecificPart() {
+ final URI uri = UriBuilder.fromUri("mailto:a@b").schemeSpecificPart("c@d").build();
+ Assert.assertEquals("mailto:c@d", uri.toString());
+ }
+
+ @Test
+ public void testOpaqueReplaceUri() {
+ final URI uri = UriBuilder.fromUri("mailto:a@b").uri(URI.create("c@d")).build();
+ Assert.assertEquals("mailto:c@d", uri.toString());
+ }
+
+ @Test
+ public void testReplaceScheme() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").scheme("https").build();
+ Assert.assertEquals("https://localhost:8080/a/b/c", uri.toString());
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").scheme(null).build();
+ Assert.assertEquals("//localhost:8080/a/b/c", uri.toString());
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").scheme(null).host(null).build();
+ Assert.assertEquals("//:8080/a/b/c", uri.toString());
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").scheme(null).host(null).port(-1).build();
+ Assert.assertEquals("/a/b/c", uri.toString());
+ }
+
+ @Test
+ public void testReplaceSchemeSpecificPart() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").schemeSpecificPart("//localhost:8080/a/b/c/d").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/d"), uri);
+ }
+
+ @Test
+ public void testNameAuthorityUri() {
+ final URI uri = UriBuilder.fromUri("http://x_y/a/b/c").build();
+ Assert.assertEquals(URI.create("http://x_y/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplaceNameAuthorityUriWithHost() {
+ final URI uri = UriBuilder.fromUri("http://x_y.com/a/b/c").host("xy.com").build();
+ Assert.assertEquals(URI.create("http://xy.com/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplaceNameAuthorityUriWithSSP() {
+ URI uri = UriBuilder.fromUri("http://x_y.com/a/b/c").schemeSpecificPart("//xy.com/a/b/c").build();
+ Assert.assertEquals(URI.create("http://xy.com/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://x_y.com/a/b/c").schemeSpecificPart("//v_w.com/a/b/c").build();
+ Assert.assertEquals(URI.create("http://v_w.com/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplaceUserInfo() {
+ final URI uri = UriBuilder.fromUri("http://bob@localhost:8080/a/b/c").userInfo("sue").build();
+ Assert.assertEquals(URI.create("http://sue@localhost:8080/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplaceHost() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").host("a.com").build();
+ Assert.assertEquals(URI.create("http://a.com:8080/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").host("[::FFFF:129.144.52.38]").build();
+ Assert.assertEquals(URI.create("http://[::FFFF:129.144.52.38]:8080/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplacePort() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").port(9090).build();
+ Assert.assertEquals(URI.create("http://localhost:9090/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").port(-1).build();
+ Assert.assertEquals(URI.create("http://localhost/a/b/c"), uri);
+ }
+
+ @Test
+ public void testReplacePath() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").replacePath("/x/y/z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/x/y/z"), uri);
+ }
+
+ @Test
+ public void testReplacePathNull() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").replacePath(null).build();
+
+ Assert.assertEquals(URI.create("http://localhost:8080"), uri);
+ }
+
+ @Test
+ public void testReplaceMatrix() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c;a=x;b=y").replaceMatrix("x=a;y=b").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c;x=a;y=b"), uri);
+ }
+
+ @Test
+ public void testReplaceMatrixParams() {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost:8080/a/b/c;a=x;b=y").replaceMatrixParam("a", "z", "zz");
+
+ {
+ final URI uri = ubu.build();
+ final List<PathSegment> ps = UriComponent.decodePath(uri, true);
+ final MultivaluedMap<String, String> mps = ps.get(2).getMatrixParameters();
+ final List<String> a = mps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ final List<String> b = mps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ }
+
+ {
+ final URI uri = ubu.replaceMatrixParam("a", "_z_", "_zz_").build();
+ final List<PathSegment> ps = UriComponent.decodePath(uri, true);
+ final MultivaluedMap<String, String> mps = ps.get(2).getMatrixParameters();
+ final List<String> a = mps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("_z_", a.get(0));
+ Assert.assertEquals("_zz_", a.get(1));
+ final List<String> b = mps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ }
+
+ {
+ final URI uri = JerseyUriBuilder.fromUri("http://localhost:8080/a/b/c;a=x;b=y").replaceMatrixParam("a", "z", "zz")
+ .matrixParam("c", "c").path(
+ "d").build();
+
+ final List<PathSegment> ps = UriComponent.decodePath(uri, true);
+ final MultivaluedMap<String, String> mps = ps.get(2).getMatrixParameters();
+ final List<String> a = mps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ final List<String> b = mps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ final List<String> c = mps.get("c");
+ Assert.assertEquals(1, c.size());
+ Assert.assertEquals("c", c.get(0));
+ }
+
+ {
+ final URI uri = JerseyUriBuilder.fromUri("http://localhost:8080/a;w=123;q=15/b/c;a=x;b=y").replaceMatrixParam("a",
+ "z", "zz").matrixParam("c", "c").path("d").build();
+
+ final List<PathSegment> ps = UriComponent.decodePath(uri, true);
+ MultivaluedMap<String, String> mps = ps.get(0).getMatrixParameters();
+
+ List<String> w = mps.get("w");
+ Assert.assertEquals(1, w.size());
+ Assert.assertEquals("123", w.get(0));
+
+ w = mps.get("q");
+ Assert.assertEquals(1, w.size());
+ Assert.assertEquals("15", w.get(0));
+
+ mps = ps.get(2).getMatrixParameters();
+ final List<String> a = mps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ final List<String> b = mps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ final List<String> c = mps.get("c");
+ Assert.assertEquals(1, c.size());
+ Assert.assertEquals("c", c.get(0));
+ }
+ }
+
+ @Test
+ public void testReplaceMatrixParamsEmpty() {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost:8080/a/b/c").replaceMatrixParam("a", "z", "zz");
+ {
+ final URI uri = ubu.build();
+ final List<PathSegment> ps = UriComponent.decodePath(uri, true);
+ final MultivaluedMap<String, String> mps = ps.get(2).getMatrixParameters();
+ final List<String> a = mps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ }
+ }
+
+ @Test
+ public void testReplaceMatrixParamsEncoded() throws URISyntaxException {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost/").replaceMatrix("limit=10;sql=select+*+from+users");
+ ubu.replaceMatrixParam("limit", 100);
+
+ final URI uri = ubu.build();
+ Assert.assertEquals(URI.create("http://localhost/;limit=100;sql=select+*+from+users"), uri);
+ }
+
+ @Test
+ public void testMatrixParamsWithTheSameName() {
+ UriBuilder first = UriBuilder.fromUri("http://www.com/").replaceMatrixParam("example", "one", "two");
+ first = first.path("/child");
+ first = first.replaceMatrixParam("example", "another");
+
+ Assert.assertEquals("http://www.com/;example=one;example=two/child;example=another", first.build().toString());
+ }
+
+ @Test
+ public void testMatrixParamsWithTheDifferentName() {
+ UriBuilder first = UriBuilder.fromUri("http://www.com/").replaceMatrixParam("example", "one", "two");
+ first = first.path("/child");
+ first = first.replaceMatrixParam("other", "another");
+
+ Assert.assertEquals("http://www.com/;example=one;example=two/child;other=another", first.build().toString());
+ }
+
+ @Test
+ public void testReplaceQuery() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c?a=x&b=y").replaceQuery("x=a&y=b").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?x=a&y=b"), uri);
+ }
+
+ @Test
+ public void testBuildEncodedQuery() {
+ URI u = UriBuilder.fromPath("").queryParam("y", "1 %2B 2").build();
+ Assert.assertEquals(URI.create("?y=1+%2B+2"), u);
+
+ // Issue 216
+ u = UriBuilder.fromPath("http://localhost:8080").path("/{x}/{y}/{z}/{x}").buildFromEncoded("%xy", " ", "=");
+ Assert.assertEquals(URI.create("http://localhost:8080/%25xy/%20/=/%25xy"), u);
+ }
+
+ @Test
+ public void testReplaceQueryParams() {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost:8080/a/b/c?a=x&b=y").replaceQueryParam("a", "z", "zz")
+ .queryParam("c", "c");
+
+ {
+ final URI uri = ubu.build();
+
+ final MultivaluedMap<String, String> qps = UriComponent.decodeQuery(uri, true);
+ final List<String> a = qps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ final List<String> b = qps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ final List<String> c = qps.get("c");
+ Assert.assertEquals(1, c.size());
+ Assert.assertEquals("c", c.get(0));
+ }
+
+ {
+ final URI uri = ubu.replaceQueryParam("a", "_z_", "_zz_").build();
+
+ final MultivaluedMap<String, String> qps = UriComponent.decodeQuery(uri, true);
+ final List<String> a = qps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("_z_", a.get(0));
+ Assert.assertEquals("_zz_", a.get(1));
+ final List<String> b = qps.get("b");
+ Assert.assertEquals(1, b.size());
+ Assert.assertEquals("y", b.get(0));
+ final List<String> c = qps.get("c");
+ Assert.assertEquals(1, c.size());
+ Assert.assertEquals("c", c.get(0));
+ }
+
+ // issue 257 - param is removed after setting it to null
+ {
+ final URI u1 = UriBuilder.fromPath("http://localhost:8080").queryParam("x", "10")
+ .replaceQueryParam("x", (Object[]) null)
+ .build();
+ Assert.assertTrue(u1.toString().equals("http://localhost:8080"));
+
+ final URI u2 = UriBuilder.fromPath("http://localhost:8080").queryParam("x", "10").replaceQueryParam("x").build();
+ Assert.assertTrue(u2.toString().equals("http://localhost:8080"));
+ }
+
+ // issue 257 - IllegalArgumentException
+ {
+ boolean caught = false;
+
+ try {
+ UriBuilder.fromPath("http://localhost:8080").queryParam("x", "10").replaceQueryParam("x", "1", null, "2").build();
+ } catch (final IllegalArgumentException iae) {
+ caught = true;
+ }
+
+ Assert.assertTrue(caught);
+ }
+
+ }
+
+ @Test
+ public void testReplaceQueryParamsEmpty() {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost:8080/a/b/c").replaceQueryParam("a", "z", "zz")
+ .queryParam("c", "c");
+
+ {
+ final URI uri = ubu.build();
+
+ final MultivaluedMap<String, String> qps = UriComponent.decodeQuery(uri, true);
+ final List<String> a = qps.get("a");
+ Assert.assertEquals(2, a.size());
+ Assert.assertEquals("z", a.get(0));
+ Assert.assertEquals("zz", a.get(1));
+ final List<String> c = qps.get("c");
+ Assert.assertEquals(1, c.size());
+ Assert.assertEquals("c", c.get(0));
+ }
+ }
+
+ @Test
+ public void testReplaceQueryParamsEncoded1() throws URISyntaxException {
+ final UriBuilder ubu = UriBuilder.fromUri(new URI("http://localhost/")).replaceQuery("limit=10&sql=select+*+from+users");
+ ubu.replaceQueryParam("limit", 100);
+
+ final URI uri = ubu.build();
+ Assert.assertEquals(URI.create("http://localhost/?limit=100&sql=select+%2A+from+users"), uri);
+ }
+
+ @Test
+ public void testReplaceQueryParamsEncoded2() throws URISyntaxException {
+ final UriBuilder ubu = UriBuilder.fromUri(new URI("http://localhost")).replaceQuery("limit=10&sql=select+*+from+users");
+ ubu.replaceQueryParam("limit", 100);
+
+ final URI uri = ubu.build();
+ Assert.assertEquals(URI.create("http://localhost/?limit=100&sql=select+%2A+from+users"), uri);
+ }
+
+ @Test
+ public void testReplaceQueryParamsEncoded3() throws URISyntaxException {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost/").replaceQuery("limit=10&sql=select+*+from+users");
+ ubu.replaceQueryParam("limit", 100);
+
+ final URI uri = ubu.build();
+ Assert.assertEquals(URI.create("http://localhost/?limit=100&sql=select+%2A+from+users"), uri);
+ }
+
+ @Test
+ public void testReplaceQueryParamsEncoded4() throws URISyntaxException {
+ final UriBuilder ubu = UriBuilder.fromUri("http://localhost").replaceQuery("limit=10&sql=select+*+from+users");
+ ubu.replaceQueryParam("limit", 100);
+
+ final URI uri = ubu.build();
+ Assert.assertEquals(URI.create("http://localhost/?limit=100&sql=select+%2A+from+users"), uri);
+ }
+
+ @Test
+ public void testReplaceFragment() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c?a=x&b=y#frag").fragment("ment").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=x&b=y#ment"), uri);
+ }
+
+ @Test
+ public void testReplaceUri() {
+ final URI u = URI.create("http://bob@localhost:8080/a/b/c?a=x&b=y#frag");
+
+ URI uri = UriBuilder.fromUri(u).uri(URI.create("https://bob@localhost:8080")).build();
+ Assert.assertEquals(URI.create("https://bob@localhost:8080/a/b/c?a=x&b=y#frag"), uri);
+
+ uri = UriBuilder.fromUri(u).uri(URI.create("https://sue@localhost:8080")).build();
+ Assert.assertEquals(URI.create("https://sue@localhost:8080/a/b/c?a=x&b=y#frag"), uri);
+
+ uri = UriBuilder.fromUri(u).uri(URI.create("https://sue@localhost:9090")).build();
+ Assert.assertEquals(URI.create("https://sue@localhost:9090/a/b/c?a=x&b=y#frag"), uri);
+
+ uri = UriBuilder.fromUri(u).uri(URI.create("/x/y/z")).build();
+ Assert.assertEquals(URI.create("http://bob@localhost:8080/x/y/z?a=x&b=y#frag"), uri);
+
+ uri = UriBuilder.fromUri(u).uri(URI.create("?x=a&b=y")).build();
+ Assert.assertEquals(URI.create("http://bob@localhost:8080/a/b/c?x=a&b=y#frag"), uri);
+
+ uri = UriBuilder.fromUri(u).uri(URI.create("#ment")).build();
+ Assert.assertEquals(URI.create("http://bob@localhost:8080/a/b/c?a=x&b=y#ment"), uri);
+ }
+
+ @Test
+ public void testSchemeSpecificPart() {
+ final URI u = URI.create("http://bob@localhost:8080/a/b/c?a=x&b=y#frag");
+
+ final URI uri = UriBuilder.fromUri(u).schemeSpecificPart("//sue@remotehost:9090/x/y/z?x=a&y=b").build();
+ Assert.assertEquals(URI.create("http://sue@remotehost:9090/x/y/z?x=a&y=b#frag"), uri);
+ }
+
+ @Test
+ public void testAppendPath() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080").path("a/b/c").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/").path("a/b/c").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080").path("/a/b/c").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c/").path("/").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c/").path("/x/y/z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/x/y/z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("x/y/z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a%20/b%20/c%20").path("/x /y /z ").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a%20/b%20/c%20/x%20/y%20/z%20"), uri);
+ }
+
+ @Test
+ public void testAppendSegment() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080").segment("a/b/c;x").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a%2Fb%2Fc%3Bx"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInPathParams() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa/{ par1}/").path("bbb/{ par2 }/ccc")
+ .build("1param", "2param");
+ assertEquals(URI.create("http://localhost:80/aaa/1param/bbb/2param/ccc"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInPathParamsByResolve() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa/{ par1}/").path("bbb/{ par2 }/ccc")
+ .build("1param", "2param");
+ assertEquals(URI.create("http://localhost:80/aaa/1param/bbb/2param/ccc"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInPathParams2() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa/{ par1}").path("bbb/{ par2 : \\d* }/ccc")
+ .build("1param", "2");
+ assertEquals(URI.create("http://localhost:80/aaa/1param/bbb/2/ccc"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInPathParams2ByResolve() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa/{ par1}").path("bbb/{ par2 : \\d* }/ccc")
+ .resolveTemplate("par1", "1param").resolveTemplate("par2", "2").build();
+ assertEquals(URI.create("http://localhost:80/aaa/1param/bbb/2/ccc"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInQueryParams() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa?a={ param : \\.d* }").build("5");
+ assertEquals(URI.create("http://localhost:80/aaa?a=5"), uri);
+ }
+
+ @Test
+ public void testWhitespacesInQueryParamsByResolve() {
+ final URI uri = UriBuilder.fromUri("http://localhost:80/aaa?a={ param : \\.d* }").resolveTemplate("param", "5")
+ .build();
+ assertEquals(URI.create("http://localhost:80/aaa?a=5"), uri);
+ }
+
+ @Test
+ public void testRelativeFromUri() {
+ URI uri = UriBuilder.fromUri("a/b/c").build();
+ Assert.assertEquals(URI.create("a/b/c"), uri);
+
+ uri = UriBuilder.fromUri("a/b/c").path("d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromUri("a/b/c/").path("d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromUri("a/b/c").path("/d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromUri("a/b/c/").path("/d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromUri("").queryParam("x", "y").build();
+ Assert.assertEquals(URI.create("?x=y"), uri);
+
+ }
+
+ @Test
+ public void testRelativefromPath() {
+ URI uri = UriBuilder.fromPath("a/b/c").build();
+ Assert.assertEquals(URI.create("a/b/c"), uri);
+
+ uri = UriBuilder.fromPath("a/b/c").path("d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromPath("a/b/c/").path("d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromPath("a/b/c").path("/d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromPath("a/b/c/").path("/d").build();
+ Assert.assertEquals(URI.create("a/b/c/d"), uri);
+
+ uri = UriBuilder.fromPath("").queryParam("x", "y").build();
+ Assert.assertEquals(URI.create("?x=y"), uri);
+ }
+
+ @Test
+ public void testAppendQueryParams() throws URISyntaxException {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c?a=x&b=y").queryParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=x&b=y&c=z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c?a=x&b=y").queryParam("c= ", "z= ").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=x&b=y&c%3D+=z%3D+"), uri);
+
+ uri = UriBuilder.fromUri(new URI("http://localhost:8080/")).queryParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/?c=z"), uri);
+
+ uri = UriBuilder.fromUri(new URI("http://localhost:8080")).queryParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/?c=z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/").queryParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/?c=z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080").queryParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/?c=z"), uri);
+
+ try {
+ UriBuilder.fromPath("http://localhost:8080").queryParam("name", "x", null).build();
+ fail("IllegalArgumentException expected.");
+ } catch (final IllegalArgumentException e) {
+ // exception expected, move on...
+ }
+ }
+
+ @Test
+ public void testAppendMatrixParams() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c;a=x;b=y").matrixParam("c", "z").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c;a=x;b=y;c=z"), uri);
+
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c;a=x;b=y").matrixParam("c=/ ;", "z=/ ;").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c;a=x;b=y;c%3D%2F%20%3B=z%3D%2F%20%3B"), uri);
+ }
+
+ @Test
+ public void testAppendPathAndMatrixParams() {
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/").path(
+ "a").matrixParam("x", "foo").matrixParam("y", "bar").path("b").matrixParam("x", "foo").matrixParam("y", "bar")
+ .build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a;x=foo;y=bar/b;x=foo;y=bar"), uri);
+ }
+
+ @Path("resource")
+ class Resource {
+
+ @GET
+ @Path("method")
+ public String get() {
+ return "";
+ }
+
+ @Path("locator")
+ public Object locator() {
+ return null;
+ }
+ }
+
+ @Test
+ public void testResourceAppendPath() throws NoSuchMethodException {
+ URI ub = UriBuilder.fromUri("http://localhost:8080/base").path(Resource.class).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/base/resource"), ub);
+
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(Resource.class, "get").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method"), ub);
+
+ final Method get = Resource.class.getMethod("get");
+ final Method locator = Resource.class.getMethod("locator");
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(get).path(locator).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method/locator"), ub);
+ }
+
+ @Path("resource/{id}")
+ class ResourceWithTemplate {
+
+ @GET
+ @Path("method/{id1}")
+ public String get() {
+ return "";
+ }
+
+ @Path("locator/{id2}")
+ public Object locator() {
+ return null;
+ }
+ }
+
+ @Test
+ public void testResourceWithTemplateAppendPath() throws NoSuchMethodException {
+ URI ub = UriBuilder.fromUri("http://localhost:8080/base").path(ResourceWithTemplate.class).build("foo");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/resource/foo"), ub);
+
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(ResourceWithTemplate.class, "get").build("foo");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method/foo"), ub);
+
+ final Method get = ResourceWithTemplate.class.getMethod("get");
+ final Method locator = ResourceWithTemplate.class.getMethod("locator");
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(get).path(locator).build("foo", "bar");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method/foo/locator/bar"), ub);
+ }
+
+ @Path("resource/{id: .+}")
+ class ResourceWithTemplateRegex {
+
+ @GET
+ @Path("method/{id1: .+}")
+ public String get() {
+ return "";
+ }
+
+ @Path("locator/{id2: .+}")
+ public Object locator() {
+ return null;
+ }
+ }
+
+ @Test
+ public void testResourceWithTemplateRegexAppendPath() throws NoSuchMethodException {
+ URI ub = UriBuilder.fromUri("http://localhost:8080/base").path(ResourceWithTemplateRegex.class).build("foo");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/resource/foo"), ub);
+
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(ResourceWithTemplateRegex.class, "get").build("foo");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method/foo"), ub);
+
+ final Method get = ResourceWithTemplateRegex.class.getMethod("get");
+ final Method locator = ResourceWithTemplateRegex.class.getMethod("locator");
+ ub = UriBuilder.fromUri("http://localhost:8080/base").path(get).path(locator).build("foo", "bar");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/method/foo/locator/bar"), ub);
+ }
+
+ interface GenericInterface<T, U> {
+
+ T find(U u);
+ }
+
+ @Path("resource/")
+ class ResourceWithGenericInterface implements GenericInterface<Object, String> {
+
+ @GET
+ @Path("{id}")
+ @Override
+ public Object find(@PathParam("id") final String s) {
+ return null;
+ }
+ }
+
+ @Test
+ public void testResourceWithGenericInterfaceAppendPath() {
+ final URI ub = UriBuilder.fromUri("http://localhost:8080/base").path(ResourceWithGenericInterface.class, "find")
+ .build("foo");
+ Assert.assertEquals(URI.create("http://localhost:8080/base/foo"), ub);
+ }
+
+ @Test
+ public void testBuildTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").build("x", "y", "z");
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").buildFromMap(m);
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testBuildTemplatesByResolve() {
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+
+ final URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").resolveTemplates(m)
+ .build();
+
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testBuildTemplatesWithNameAuthority() {
+ URI uri = UriBuilder.fromUri("http://x_y.com:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").build("x", "y", "z");
+ Assert.assertEquals(URI.create("http://x_y.com:8080/a/b/c/x/y/z/x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://x_y.com:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").buildFromMap(m);
+ Assert.assertEquals(URI.create("http://x_y.com:8080/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testBuildTemplatesWithNameAuthorityByResolve() {
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ final URI uri = UriBuilder.fromUri("http://x_y.com:8080/a/b/c")
+ .path("/{foo}/{bar}/{baz}/{foo}").buildFromMap(m);
+ Assert.assertEquals(URI.create("http://x_y.com:8080/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testBuildFromMap() {
+ final Map<String, Object> maps = new HashMap<String, Object>();
+ maps.put("x", null);
+ maps.put("y", "/path-absolute/test1");
+ maps.put("z", "fred@example.com");
+ maps.put("w", "path-rootless/test2");
+ maps.put("u", "extra");
+
+ boolean caught = false;
+
+ try {
+ System.out.println(UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}").buildFromEncodedMap(maps));
+
+ } catch (final IllegalArgumentException ex) {
+ caught = true;
+ }
+
+ Assert.assertTrue(caught);
+ }
+
+ @Test
+ public void testBuildFromMapByResolve() {
+ final Map<String, Object> maps = new HashMap<String, Object>();
+ maps.put("x", null);
+ maps.put("y", "/path-absolute/test1");
+ maps.put("z", "fred@example.com");
+ maps.put("w", "path-rootless/test2");
+ maps.put("u", "extra");
+
+ boolean caught = false;
+
+ try {
+ System.out.println(UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}").resolveTemplates(maps).build());
+
+ } catch (final IllegalArgumentException ex) {
+ caught = true;
+ }
+
+ Assert.assertTrue(caught);
+ }
+
+ @Test
+ public void testBuildQueryTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}").build("=+&%xx%20");
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%2520"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("b", "=+&%xx%20");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}").buildFromMap(m);
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%2520"), uri);
+ }
+
+ @Test
+ public void testBuildFromEncodedQueryTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}").buildFromEncoded("=+&%xx%20");
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%20"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("b", "=+&%xx%20");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}").buildFromEncodedMap(m);
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%20"), uri);
+ }
+
+ @Test
+ public void testBuildFromEncodedSlashInParamValue() {
+ assertEquals("/A/B", UriBuilder.fromUri("/{param}").buildFromEncoded("A/B").toString());
+ }
+
+ @Test
+ public void testResolveTemplateFromEncodedQueryTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}")
+ .resolveTemplateFromEncoded("b", "=+&%xx%20").build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%20"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("b", "=+&%xx%20");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").queryParam("a", "{b}").resolveTemplatesFromEncoded(m).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c?a=%3D%2B%26%25xx%20"), uri);
+ }
+
+ @Test
+ public void testBuildFragmentTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").fragment("{foo}")
+ .build("x", "y", "z");
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x#x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").fragment("{foo}")
+ .buildFromMap(m);
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x#x"), uri);
+ }
+
+ @Test
+ public void testResolveTemplateFromFragmentTemplates() {
+ URI uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").fragment("{foo}")
+ .resolveTemplate("foo", "x").resolveTemplate("bar", "y")
+ .resolveTemplate("baz", "z").build();
+
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x#x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://localhost:8080/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").fragment("{foo}")
+ .resolveTemplates(m).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/a/b/c/x/y/z/x#x"), uri);
+ }
+
+ @Test
+ public void testTemplatesDefaultPort() {
+ URI uri = UriBuilder.fromUri("http://localhost/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").build("x", "y", "z");
+ Assert.assertEquals(URI.create("http://localhost/a/b/c/x/y/z/x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://localhost/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").buildFromMap(m);
+ Assert.assertEquals(URI.create("http://localhost/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testResolveTemplatesDefaultPort() {
+ URI uri = UriBuilder.fromUri("http://localhost/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").resolveTemplate("foo", "x")
+ .resolveTemplate("bar", "y").resolveTemplate("baz" + "", "z").build();
+ Assert.assertEquals(URI.create("http://localhost/a/b/c/x/y/z/x"), uri);
+
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("foo", "x");
+ m.put("bar", "y");
+ m.put("baz", "z");
+ uri = UriBuilder.fromUri("http://localhost/a/b/c").path("/{foo}/{bar}/{baz}/{foo}").resolveTemplates(m).build();
+ Assert.assertEquals(URI.create("http://localhost/a/b/c/x/y/z/x"), uri);
+ }
+
+ @Test
+ public void testClone() {
+ final UriBuilder ub = UriBuilder.fromUri("http://user@localhost:8080/?query#fragment").path("a");
+ final URI full = ub.clone().path("b").build();
+ final URI base = ub.build();
+
+ Assert.assertEquals(URI.create("http://user@localhost:8080/a?query#fragment"), base);
+ Assert.assertEquals(URI.create("http://user@localhost:8080/a/b?query#fragment"), full);
+ }
+
+ @Test
+ public void testIllegalArgumentException() {
+ boolean caught = false;
+ try {
+ UriBuilder.fromPath(null);
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+
+ caught = false;
+ try {
+ UriBuilder.fromUri((URI) null);
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+
+ caught = false;
+ try {
+ UriBuilder.fromUri((String) null);
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+ }
+
+ @Test
+ public void testUriEncoding() {
+ final URI expected = URI.create("http://localhost:8080/%5E");
+ assertEquals(expected, new JerseyUriBuilder().uri("http://localhost:8080/^").build());
+ assertEquals(expected, UriBuilder.fromUri("http://localhost:8080/^").build());
+ }
+
+ // Regression test for JERSEY-1324 fix.
+ @Test
+ public void testInvalidUriTemplateEncodedAsPath() {
+ assertEquals(URI.create("http%20ftp%20xml//:888:888/1:8080:80"),
+ new JerseyUriBuilder().uri("http ftp xml//:888:888/1:8080:80").build());
+ }
+
+ @Test
+ public void testVariableWithoutValue() {
+ boolean caught = false;
+ try {
+ UriBuilder.fromPath("http://localhost:8080").path("/{a}/{b}").buildFromEncoded("aVal");
+
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+ }
+
+ @Test
+ public void testPortValue() {
+ boolean caught = false;
+ try {
+ UriBuilder.fromPath("http://localhost").port(-2);
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+ }
+
+ @Test
+ public void testPortSetting() throws URISyntaxException {
+ URI uri;
+
+ uri = new JerseyUriBuilder().uri("http://localhost").port(8080).build();
+ Assert.assertEquals(URI.create("http://localhost:8080"), uri);
+
+ uri = new JerseyUriBuilder().uri(new URI("http://localhost")).port(8080).build();
+ Assert.assertEquals(URI.create("http://localhost:8080"), uri);
+
+ uri = new JerseyUriBuilder().uri("http://localhost/").port(8080).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/"), uri);
+
+ uri = new JerseyUriBuilder().uri(new URI("http://localhost/")).port(8080).build();
+ Assert.assertEquals(URI.create("http://localhost:8080/"), uri);
+ }
+
+ @Test
+ public void testHostValue() {
+ boolean caught = false;
+ try {
+ UriBuilder.fromPath("http://localhost").host("");
+ } catch (final IllegalArgumentException e) {
+ caught = true;
+ }
+ Assert.assertTrue(caught);
+
+ URI uri = UriBuilder.fromPath("").host("abc").build();
+ Assert.assertEquals(URI.create("//abc"), uri);
+
+ uri = UriBuilder.fromPath("").host("abc").host(null).build();
+ Assert.assertEquals(URI.create(""), uri);
+ }
+
+ /**
+ * This test has been rewritten as part of fix for JERSEY-2378.
+ * The new purpose of this test is to demonstrate how old behavior of UriBuilder.build() method
+ * wrt. unresolved templates can be achieved via {@link org.glassfish.jersey.uri.UriComponent#encodeTemplateNames(String)}
+ * method.
+ */
+ @Test
+ public void testEncodeTemplateNames() {
+ final URI uri = URI.create(UriComponent.encodeTemplateNames(UriBuilder.fromPath("http://localhost:8080").path(
+ "/{a}/{b}").replaceQuery("q={c}").toTemplate()));
+ Assert.assertEquals(URI.create("http://localhost:8080/%7Ba%7D/%7Bb%7D?q=%7Bc%7D"), uri);
+ }
+
+ @Test
+ public void resolveTemplateTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}")
+ .queryParam("query", "{q}");
+ uriBuilder.resolveTemplate("a", "param-a");
+ uriBuilder.resolveTemplate("q", "param-q");
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("a", "ignored-a");
+ m.put("b", "param-b");
+ m.put("q", "ignored-q");
+ Assert.assertEquals(URI.create("http://localhost:8080/param-a/param-b?query=param-q"), uriBuilder.buildFromMap(m));
+ }
+
+ @Test
+ public void resolveTemplateFromEncodedTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}").path("{c}")
+ .queryParam("query", "{q}");
+ uriBuilder.resolveTemplateFromEncoded("a", "x/y/z%3F%20");
+ uriBuilder.resolveTemplateFromEncoded("q", "q?%20%26");
+ uriBuilder.resolveTemplate("c", "paramc1/paramc2");
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("a", "ignored-a");
+ m.put("b", "param-b/aaa");
+ m.put("q", "ignored-q");
+ Assert.assertEquals("http://localhost:8080/x/y/z%3F%20/param-b/aaa/paramc1%2Fparamc2?query=q%3F%20%26",
+ uriBuilder.buildFromEncodedMap(m).toString());
+ }
+
+ @Test
+ public void resolveTemplateWithoutEncodedTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}").path("{c}")
+ .queryParam("query", "{q}");
+ uriBuilder.resolveTemplate("a", "x/y/z%3F%20");
+ uriBuilder.resolveTemplate("q", "q?%20%26");
+ uriBuilder.resolveTemplate("c", "paramc1/paramc2");
+ final Map<String, Object> m = new HashMap<String, Object>();
+ m.put("a", "ignored-a");
+ m.put("b", "param-b/aaa");
+ m.put("q", "ignored-q");
+ Assert.assertEquals("http://localhost:8080/x%2Fy%2Fz%253F%2520/param-b%2Faaa/paramc1%2Fparamc2?query=q%3F%2520%2526",
+ uriBuilder.buildFromMap(m).toString());
+ }
+
+ @Test
+ public void resolveTemplateWithEncodedSlashTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}")
+ .queryParam("query", "{q}");
+ uriBuilder.resolveTemplate("a", "param-a/withSlash", false);
+ uriBuilder.resolveTemplate("b", "param-b/withEncodedSlash", true);
+ uriBuilder.resolveTemplate("q", "param-q", true);
+ Assert.assertEquals(URI.create("http://localhost:8080/param-a/withSlash/param-b%2FwithEncodedSlash?query=param-q"),
+ uriBuilder.build());
+ uriBuilder.build();
+ }
+
+ @Test
+ public void resolveTemplatesTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}")
+ .queryParam("query", "{q}");
+
+ uriBuilder.resolveTemplate("a", "param-a");
+ uriBuilder.resolveTemplate("q", "param-q");
+ final Map<String, Object> buildMap = new HashMap<String, Object>();
+ buildMap.put("a", "ignored-a");
+ buildMap.put("b", "param-b");
+ buildMap.put("q", "ignored-q");
+ Assert.assertEquals(URI.create("http://localhost:8080/param-a/param-b?query=param-q"), uriBuilder.buildFromMap(buildMap));
+ }
+
+ @Test
+ public void resolveTemplatesFromEncodedTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}").path("{c}")
+ .queryParam("query", "{q}");
+
+ final Map<String, Object> resolveMap = new HashMap<String, Object>();
+ resolveMap.put("a", "x/y/z%3F%20");
+ resolveMap.put("q", "q?%20%26");
+ resolveMap.put("c", "paramc1/paramc2");
+ uriBuilder.resolveTemplatesFromEncoded(resolveMap);
+ final Map<String, Object> buildMap = new HashMap<String, Object>();
+ buildMap.put("b", "param-b/aaa");
+ Assert.assertEquals("http://localhost:8080/x/y/z%3F%20/param-b/aaa/paramc1/paramc2?query=q%3F%20%26",
+ uriBuilder.buildFromEncodedMap(buildMap).toString());
+ }
+
+ @Test
+ public void resolveTemplatesFromNotEncodedTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}").path("{c}")
+ .queryParam("query", "{q}");
+
+ final Map<String, Object> resolveMap = new HashMap<String, Object>();
+ resolveMap.put("a", "x/y/z%3F%20");
+ resolveMap.put("q", "q?%20%26");
+ resolveMap.put("c", "paramc1/paramc2");
+ uriBuilder.resolveTemplates(resolveMap);
+ final Map<String, Object> buildMap = new HashMap<String, Object>();
+ buildMap.put("b", "param-b/aaa");
+ Assert.assertEquals("http://localhost:8080/x%2Fy%2Fz%253F%2520/param-b%2Faaa/paramc1%2Fparamc2?query=q%3F%2520%2526",
+ uriBuilder.buildFromMap(buildMap).toString());
+ }
+
+ @Test
+ public void resolveTemplatesEncodeSlash() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}").path("{c}")
+ .queryParam("query", "{q}");
+
+ final Map<String, Object> resolveMap = new HashMap<String, Object>();
+ resolveMap.put("a", "x/y/z%3F%20");
+ resolveMap.put("q", "q?%20%26");
+ resolveMap.put("c", "paramc1/paramc2");
+ uriBuilder.resolveTemplates(resolveMap, false);
+ final Map<String, Object> buildMap = new HashMap<String, Object>();
+ buildMap.put("b", "param-b/aaa");
+ Assert.assertEquals("http://localhost:8080/x/y/z%253F%2520/param-b/aaa/paramc1/paramc2?query=q%3F%2520%2526",
+ uriBuilder.buildFromMap(buildMap, false).toString());
+ }
+
+ @Test
+ public void resolveTemplatesWithEncodedSlashTest() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{a}").path("{b}")
+ .queryParam("query", "{q}");
+ final Map<String, Object> resolveMap = new HashMap<String, Object>();
+ resolveMap.put("a", "param-a/withSlash");
+ resolveMap.put("q", "param-q");
+ uriBuilder.resolveTemplates(resolveMap, false);
+ uriBuilder.resolveTemplate("b", "param-b/withEncodedSlash", true);
+ Assert.assertEquals(URI.create("http://localhost:8080/param-a/withSlash/param-b%2FwithEncodedSlash?query=param-q"),
+ uriBuilder.build());
+ uriBuilder.build();
+ }
+
+ @Test
+ public void resolveTemplateMultipleCall() {
+ final UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost:8080").path("{start}").path("{a}")
+ .resolveTemplate("a", "first-a").path("{a}").resolveTemplate("a", "second-a")
+ .path("{a}/{a}").resolveTemplate("a", "twice-a");
+
+ Assert.assertEquals(URI.create("http://localhost:8080/start-path/first-a/second-a/twice-a/twice-a"),
+ uriBuilder.build("start-path"));
+ }
+
+ @Test
+ public void replaceWithEmtpySchemeFromUriTest() throws URISyntaxException {
+ final String uriOrig = "ftp://ftp.is.co.za/rfc/rfc1808.txt";
+ final URI uriReplace = new URI(null, "ftp.is.co.za", "/test/rfc1808.txt", null, null);
+ final URI uri = UriBuilder.fromUri(new URI(uriOrig)).uri(uriReplace).build();
+ Assert.assertEquals("ftp://ftp.is.co.za/test/rfc1808.txt", uri.toString());
+ }
+
+ @Test
+ public void replaceWithEmptySchemeFromStringTest() throws URISyntaxException {
+ final String uriOrig = "ftp://ftp.is.co.za/rfc/rfc1808.txt";
+ final URI uriReplace = new URI(null, "ftp.is.co.za", "/test/rfc1808.txt", null, null);
+
+ final URI uri = UriBuilder.fromUri(new URI(uriOrig)).uri(uriReplace.toASCIIString()).build();
+ Assert.assertEquals("ftp://ftp.is.co.za/test/rfc1808.txt", uri.toString());
+ }
+
+ @Test
+ public void replaceWithEmptyQueryFromStringTest() throws URISyntaxException {
+ final String uriOrig = "ftp://ftp.is.co.za/rfc/rfc1808.txt?a=1";
+ final URI uriReplace = new URI(null, "ftp.is.co.za", "/test/rfc1808.txt", null, null);
+
+ final URI uri = UriBuilder.fromUri(new URI(uriOrig)).uri(uriReplace.toASCIIString()).build();
+ Assert.assertEquals("ftp://ftp.is.co.za/test/rfc1808.txt?a=1", uri.toString());
+ }
+
+ @Test
+ public void replaceWithEmptyFragmentFromStringTest() throws URISyntaxException {
+ final String uriOrig = "ftp://ftp.is.co.za/rfc/rfc1808.txt#myFragment";
+ final URI uriReplace = new URI(null, "ftp.is.co.za", "/test/rfc1808.txt", null, null);
+
+ final URI uri = UriBuilder.fromUri(new URI(uriOrig)).uri(uriReplace.toASCIIString()).build();
+ Assert.assertEquals("ftp://ftp.is.co.za/test/rfc1808.txt#myFragment", uri.toString());
+ }
+
+ @Test
+ public void replaceOpaqueUriWithNonOpaqueFromStringTest() throws URISyntaxException {
+ final String first = "news:comp.lang.java";
+ final String second = "http://comp.lang.java";
+ UriBuilder.fromUri(new URI(first)).uri(second);
+ }
+
+ @Test
+ public void replaceOpaqueUriWithNonOpaqueFromStringTest2() throws URISyntaxException {
+ final String first = "news:comp.lang.java";
+ final String second = "http://comp.lang.java";
+ UriBuilder.fromUri(new URI(first)).scheme("http").uri(second);
+ }
+
+ @Test
+ public void replaceOpaqueUriWithNonOpaqueFromUriTest() throws URISyntaxException {
+ final String first = "news:comp.lang.java";
+ final String second = "http://comp.lang.java";
+ UriBuilder.fromUri(new URI(first)).uri(new URI(second));
+ }
+
+ @Test
+ public void testQueryParamEncoded() {
+ final UriBuilder uriBuilder = UriBuilder.fromUri("http://localhost:8080/path");
+ uriBuilder.queryParam("query", "%dummy23");
+ Assert.assertEquals("http://localhost:8080/path?query=%25dummy23", uriBuilder.build().toString());
+ }
+
+ @Test
+ public void testQueryParamEncoded2() {
+ final UriBuilder uriBuilder = UriBuilder.fromUri("http://localhost:8080/path");
+ uriBuilder.queryParam("query", "{param}");
+ Assert.assertEquals("http://localhost:8080/path?query=%25dummy23", uriBuilder.build("%dummy23").toString());
+ }
+
+ @Test
+ public void testQueryParamEncoded3() {
+ final UriBuilder uriBuilder = UriBuilder.fromUri("http://localhost:8080/path");
+ uriBuilder.queryParam("query", "{param}");
+ Assert.assertEquals("http://localhost:8080/path?query=%2525test", uriBuilder.build("%25test").toString());
+ }
+
+ @Test
+ public void testQueryParamEncoded4() {
+ final UriBuilder uriBuilder = UriBuilder.fromUri("http://localhost:8080/path");
+ uriBuilder.queryParam("query", "{param}");
+ Assert.assertEquals("http://localhost:8080/path?query=%25test", uriBuilder.buildFromEncoded("%25test").toString());
+ }
+
+ @Test
+ public void testQueryParamEncoded5() {
+ final UriBuilder uriBuilder = UriBuilder.fromUri("http://localhost:8080/path");
+ uriBuilder.queryParam("query", "! # $ & ' ( ) * + , / : ; = ? @ [ ]");
+ Assert.assertEquals(
+ "http://localhost:8080/path?query=%21+%23+%24+%26+%27+%28+%29+%2A+%2B+%2C+%2F+%3A+%3B+%3D+%3F+%40+%5B+%5D",
+ uriBuilder.build().toString());
+ }
+
+}
diff --git a/tests/e2e-core-common/src/test/resources/META-INF/services/org.glassfish.jersey.tests.e2e.common.config.TestContract b/tests/e2e-core-common/src/test/resources/META-INF/services/org.glassfish.jersey.tests.e2e.common.config.TestContract
new file mode 100644
index 0000000..9c92e56
--- /dev/null
+++ b/tests/e2e-core-common/src/test/resources/META-INF/services/org.glassfish.jersey.tests.e2e.common.config.TestContract
@@ -0,0 +1,2 @@
+org.glassfish.jersey.tests.e2e.common.config.TestServiceA
+org.glassfish.jersey.tests.e2e.common.config.TestServiceC
\ No newline at end of file
diff --git a/tests/e2e-core-common/src/test/resources/surefire.policy b/tests/e2e-core-common/src/test/resources/surefire.policy
new file mode 100644
index 0000000..4e99a5d
--- /dev/null
+++ b/tests/e2e-core-common/src/test/resources/surefire.policy
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// we do not care about java lib itself
+grant codebase "file:${java.home}/-" {
+ permission java.security.AllPermission;
+};
+
+// we do not care about our dependencies
+grant codebase "file:${settings.localRepository}/-" {
+ permission java.security.AllPermission;
+};
+
+// this is to be able to set runtime delegate instance in jax-rs from the tests
+// and to run multi-threaded tests
+grant codebase "file:${project.build.directory}/test-classes/-" {
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "write";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
+
+grant codebase "file:${project.build.directory}/classes/-" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
diff --git a/tests/e2e-entity/pom.xml b/tests/e2e-entity/pom.xml
new file mode 100644
index 0000000..46f38e2
--- /dev/null
+++ b/tests/e2e-entity/pom.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-entity</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-entity</name>
+
+ <description>Jersey E2E Entity tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-freemarker</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-mustache</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson1</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jettison</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-binding</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth2-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractParameterTypeArgumentOrderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractParameterTypeArgumentOrderTest.java
new file mode 100644
index 0000000..a81756f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractParameterTypeArgumentOrderTest.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+/**
+ * Parent for set of ParameterTypeArgumentOrder tests.
+ *
+ * Contains all the providers and resources for the tests. The resource config creation and test methods were separated into
+ * subclasses.
+ *
+ * @author Paul Sandoz
+ */
+public abstract class AbstractParameterTypeArgumentOrderTest extends JerseyTest {
+
+ @Provider
+ public static class ObjectWriter implements MessageBodyWriter {
+
+ @Override
+ public boolean isWriteable(final Class type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final Object o, final Class type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Object o, final Class type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap httpHeaders, final OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ entityStream.write(o.toString().getBytes());
+ }
+ }
+
+ public static class GenericClassWriter<T> implements MessageBodyWriter<T> {
+
+ private final Class c;
+
+ GenericClassWriter(final Class c) {
+ this.c = c;
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return c.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(final T t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final T t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write((c.getSimpleName() + type.getSimpleName()).getBytes());
+ }
+ }
+
+ public static class A {}
+
+ @Provider
+ public static class AWriter extends GenericClassWriter<A> {
+
+ public AWriter() {
+ super(A.class);
+ }
+ }
+
+ public static class B extends A {}
+
+ @Provider
+ public static class BWriter extends GenericClassWriter<B> {
+
+ public BWriter() {
+ super(B.class);
+ }
+ }
+
+ public static class C extends B {}
+
+ @Provider
+ public static class CWriter extends GenericClassWriter<C> {
+
+ public CWriter() {
+ super(C.class);
+ }
+ }
+
+ @Path("/")
+ public static class ClassResource {
+
+ @GET
+ @Path("a")
+ public A getA() {
+ return new A();
+ }
+
+ @GET
+ @Path("b")
+ public B getB() {
+ return new B();
+ }
+
+ @GET
+ @Path("c")
+ public C getC() {
+ return new C();
+ }
+ }
+
+ public static class GenericClassReaderWriter<T> implements MessageBodyWriter<T>, MessageBodyReader<T> {
+
+ private final Class c;
+
+ GenericClassReaderWriter(final Class c) {
+ this.c = c;
+ }
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return c.isAssignableFrom(type);
+ }
+
+ @Override
+ public T readFrom(final Class<T> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ try {
+ return (T) c.newInstance();
+ } catch (final Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return c.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(final T t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final T t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write((c.getSimpleName() + type.getSimpleName()).getBytes());
+ }
+ }
+
+ @Provider
+ public static class AReaderWriter<T> extends GenericClassReaderWriter<T> {
+
+ public AReaderWriter() {
+ super(A.class);
+ }
+ }
+
+ @Provider
+ public static class BReaderWriter extends GenericClassReaderWriter<B> {
+
+ public BReaderWriter() {
+ super(B.class);
+ }
+ }
+
+ @Provider
+ public static class CReaderWriter extends GenericClassReaderWriter<C> {
+
+ public CReaderWriter() {
+ super(C.class);
+ }
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractTypeTester.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractTypeTester.java
new file mode 100644
index 0000000..8f3c8a2
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/AbstractTypeTester.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Abstract entity type tester base class.
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public abstract class AbstractTypeTester extends JerseyTest {
+
+ protected static final ThreadLocal localRequestEntity = new ThreadLocal();
+
+ public abstract static class AResource<T> {
+
+ @POST
+ public T post(T t) {
+ return t;
+ }
+ }
+
+ public static class RequestEntityInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException {
+ OutputStream original = writerInterceptorContext.getOutputStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writerInterceptorContext.setOutputStream(baos);
+ writerInterceptorContext.proceed();
+ final byte[] requestEntity = baos.toByteArray();
+ writerInterceptorContext.setProperty("requestEntity", requestEntity);
+ original.write(requestEntity);
+ }
+ }
+
+ public static class ResponseFilter implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ localRequestEntity.set(requestContext.getProperty("requestEntity"));
+ }
+ }
+
+ /**
+ * Looks for all resources and providers declared as inner classes of the subclass of this class
+ * and adds them to the returned ResourceConfig (unless constrained to client side).
+ *
+ * @return ResourceConfig instance
+ */
+ @Override
+ protected Application configure() {
+ HashSet<Class<?>> classes = new HashSet<Class<?>>();
+
+ for (Class<?> cls : getClass().getDeclaredClasses()) {
+ if (cls.getAnnotation(Path.class) != null) {
+ classes.add(cls);
+ } else if (cls.getAnnotation(Provider.class) != null) {
+ final ConstrainedTo constrainedTo = cls.getAnnotation(ConstrainedTo.class);
+ if (constrainedTo == null || constrainedTo.value() == RuntimeType.SERVER) {
+ classes.add(cls);
+ }
+ }
+ }
+
+ return new ResourceConfig(classes);
+ }
+
+ /**
+ * Looks for all providers declared as inner classes of the subclass of this class
+ * and adds them to the client configuration (unless constrained to server side).
+ */
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(RequestEntityInterceptor.class);
+ config.register(ResponseFilter.class);
+
+ for (Class<?> cls : getClass().getDeclaredClasses()) {
+ if (cls.getAnnotation(Provider.class) != null) {
+ final ConstrainedTo constrainedTo = cls.getAnnotation(ConstrainedTo.class);
+ if (constrainedTo == null || constrainedTo.value() == RuntimeType.CLIENT) {
+ config.register(cls);
+ }
+ }
+ }
+ }
+
+ protected <T> void _test(T in, Class resource) {
+ _test(in, resource, true);
+ }
+
+ protected <T> void _test(T in, Class resource, MediaType m) {
+ _test(in, resource, m, true);
+ }
+
+ protected <T> void _test(T in, Class resource, boolean verify) {
+ _test(in, resource, MediaType.TEXT_PLAIN_TYPE, verify);
+ }
+
+ protected <T> void _test(T in, Class resource, MediaType m, boolean verify) {
+ WebTarget target = target(resource.getSimpleName());
+ Response response = target.request().post(Entity.entity(in, m));
+
+ byte[] inBytes = getRequestEntity();
+ byte[] outBytes = getEntityAsByteArray(response);
+
+ if (verify) {
+ _verify(inBytes, outBytes);
+ }
+ }
+
+ protected static byte[] getRequestEntity() {
+ try {
+ return (byte[]) localRequestEntity.get();
+ } finally {
+ localRequestEntity.set(null);
+ }
+ }
+
+ protected static void _verify(byte[] in, byte[] out) {
+ assertEquals(in.length, out.length);
+ for (int i = 0; i < in.length; i++) {
+ if (in[i] != out[i]) {
+ assertEquals("Index: " + i, in[i], out[i]);
+ }
+ }
+ }
+
+ protected static byte[] getEntityAsByteArray(Response r) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ ReaderWriter.writeTo(r.readEntity(InputStream.class), baos);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return baos.toByteArray();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/BeanStreamingTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/BeanStreamingTest.java
new file mode 100644
index 0000000..8882e6e
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/BeanStreamingTest.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class BeanStreamingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(getClass().getDeclaredClasses());
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ for (Class<?> c : getClass().getDeclaredClasses()) {
+ if (c.getAnnotation(Provider.class) != null) {
+ config.register(c);
+ }
+ }
+ }
+
+ @Test
+ public void testBean() throws Exception {
+ Bean b = new Bean("bean", 123, 3.1415f);
+
+ // the following should work using BeanProvider which
+ // supports Bean.class for type application/bean
+ WebTarget r = target().path("/bean");
+ r.request().post(Entity.entity(b, "application/bean"), Bean.class);
+
+ try {
+ r = target().path("/plain");
+ r.request().post(Entity.entity(b, "text/plain"), Bean.class);
+ assertFalse(false);
+ } catch (ProcessingException ex) {
+ assertTrue(true);
+ }
+ }
+
+ @Test
+ public void testBeanWild() throws Exception {
+ Bean b = new Bean("bean", 123, 3.1415f);
+
+ // the following should work using BeanWildProvider which
+ // supports Bean.class for type application/*
+ target().path("/wild").request().post(Entity.entity(b, "application/wild-bean"), Bean.class);
+ }
+
+ @Test
+ public void testBean2() throws Exception {
+ Bean2 b = new Bean2("bean", 123, 3.1415f);
+
+ target().path("/bean2").request().post(Entity.entity(b, "application/bean"), Bean2.class);
+
+ try {
+ target().path("/plain2").request().post(Entity.entity(b, "text/plain"), Bean2.class);
+ assertFalse(false);
+ } catch (ProcessingException ex) {
+ assertTrue(true);
+ }
+ }
+
+ @Test
+ public void testBean2UsingBean() throws Exception {
+ Bean2 b = new Bean2("bean", 123, 3.1415f);
+
+ // the following should work using BeanProvider which
+ // supports Bean.class for type application/bean
+ target().path("/bean").request().post(Entity.entity(b, "application/bean"), Bean2.class);
+
+ try {
+ target().path("/plain").request().post(Entity.entity(b, "text/plain"), Bean2.class);
+ fail();
+ } catch (ProcessingException ex) {
+ // good
+ }
+ }
+
+ @Test
+ public void testBean2Wild() throws Exception {
+ Bean2 b = new Bean2("bean", 123, 3.1415f);
+
+ // the following should work using BeanWildProvider which
+ // supports Bean.class for type application/*
+ target().path("/wild2").request().post(Entity.entity(b, "application/wild-bean"), Bean2.class);
+ }
+
+ @Test
+ public void testBean2WildUsingBean() throws Exception {
+ Bean2 b = new Bean2("bean", 123, 3.1415f);
+
+ // the following should work using BeanWildProvider which
+ // supports Bean.class for type application/*
+ target().path("/wild").request().post(Entity.entity(b, "application/wild-bean"), Bean2.class);
+ }
+
+ public static class Bean implements Serializable {
+ private String string;
+ private int integer;
+ private float real;
+
+ public Bean() {
+ }
+
+ public Bean(String string, int integer, float real) {
+ this.string = string;
+ this.integer = integer;
+ this.real = real;
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+
+ public int getInteger() {
+ return integer;
+ }
+
+ public void setInteger(int integer) {
+ this.integer = integer;
+ }
+
+ public float getReal() {
+ return real;
+ }
+
+ public void setReal(float real) {
+ this.real = real;
+ }
+ }
+
+ @Provider
+ @Produces("application/bean")
+ @Consumes("application/bean")
+ public static class BeanProvider extends AbstractMessageReaderWriterProvider<Bean> {
+
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean.class;
+ }
+
+ public Bean readFrom(
+ Class<Bean> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ ObjectInputStream oin = new ObjectInputStream(entityStream);
+ try {
+ return (Bean) oin.readObject();
+ } catch (ClassNotFoundException cause) {
+ IOException effect = new IOException(cause.getLocalizedMessage());
+ effect.initCause(cause);
+ throw effect;
+ }
+ }
+
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean.class;
+ }
+
+ public void writeTo(
+ Bean t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ ObjectOutputStream out = new ObjectOutputStream(entityStream);
+ out.writeObject(t);
+ out.flush();
+ }
+ }
+
+ @Provider
+ @Produces("application/*")
+ @Consumes("application/*")
+ public static class BeanWildProvider extends BeanProvider {
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean.class;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean.class;
+ }
+ }
+
+ @Provider
+ @Produces("application/bean")
+ @Consumes("application/bean")
+ public static class Bean2Provider extends AbstractMessageReaderWriterProvider<Bean2> {
+
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean2.class;
+ }
+
+ public Bean2 readFrom(
+ Class<Bean2> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ ObjectInputStream oin = new ObjectInputStream(entityStream);
+ try {
+ return (Bean2) oin.readObject();
+ } catch (ClassNotFoundException cause) {
+ IOException effect = new IOException(cause.getLocalizedMessage());
+ effect.initCause(cause);
+ throw effect;
+ }
+ }
+
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean2.class;
+ }
+
+ public void writeTo(
+ Bean2 t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ ObjectOutputStream out = new ObjectOutputStream(entityStream);
+ out.writeObject(t);
+ out.flush();
+ }
+ }
+
+ @Provider
+ @Produces("application/*")
+ @Consumes("application/*")
+ public static class Bean2WildProvider extends Bean2Provider {
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean2.class;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mt) {
+ return type == Bean2.class;
+ }
+ }
+
+ public static class Bean2 extends Bean {
+ public Bean2(String string, int integer, float real) {
+ super(string, integer, real);
+ }
+ }
+
+ @Path("/bean")
+ public static class BeanResource {
+ @POST
+ @Consumes("application/bean")
+ @Produces("application/bean")
+ public Bean post(Bean t) {
+ return t;
+ }
+ }
+
+ @Path("/bean2")
+ public static class Bean2Resource {
+ @POST
+ @Consumes("application/bean")
+ @Produces("application/bean")
+ public Bean2 post(Bean2 t) {
+ return t;
+ }
+ }
+
+ @Path("/plain")
+ public static class BeanTextPlainResource {
+ @POST
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public Bean post(Bean t) {
+ return t;
+ }
+ }
+
+ @Path("/plain2")
+ public static class Bean2TextPlainResource {
+ @POST
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public Bean2 post(Bean2 t) {
+ return t;
+ }
+ }
+
+ @Path("/wild")
+ public static class BeanWildResource {
+ @POST
+ @Consumes("application/*")
+ @Produces("application/*")
+ public Bean post(Bean t) {
+ return t;
+ }
+ }
+
+ @Path("/wild2")
+ public static class Bean2WildResource {
+ @POST
+ @Consumes("application/*")
+ @Produces("application/*")
+ public Bean2 post(Bean2 t) {
+ return t;
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/CharsetTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/CharsetTest.java
new file mode 100644
index 0000000..f81aa04
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/CharsetTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.bind.JAXBContext;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.jettison.JettisonJaxbContext;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONObject;
+import org.glassfish.jersey.client.ClientResponse;
+import org.junit.Test;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class CharsetTest extends AbstractTypeTester {
+
+ private static String[] CHARSETS = {
+ "US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16"
+ };
+
+ private static final String CONTENT = "\u00A9 CONTENT \u00FF \u2200 \u22FF";
+
+ @Path("/StringCharsetResource")
+ public static class StringCharsetResource {
+
+ @Path("US-ASCII")
+ @POST
+ @Produces("text/plain;charset=US-ASCII")
+ public String postUs_Ascii(String t) {
+ return t;
+ }
+
+ @Path("ISO-8859-1")
+ @POST
+ @Produces("text/plain;charset=ISO-8859-1")
+ public String postIso_8859_1(String t) {
+ return t;
+ }
+
+ @Path("UTF-8")
+ @POST
+ @Produces("text/plain;charset=UTF-8")
+ public String postUtf_8(String t) {
+ return t;
+ }
+
+ @Path("UTF-16BE")
+ @POST
+ @Produces("text/plain;charset=UTF-16BE")
+ public String postUtf_16be(String t) {
+ return t;
+ }
+
+ @Path("UTF-16LE")
+ @POST
+ @Produces("text/plain;charset=UTF-16LE")
+ public String postUtf_16le(String t) {
+ return t;
+ }
+
+ @Path("UTF-16")
+ @POST
+ @Produces("text/plain;charset=UTF-16")
+ public String postUtf_16(String t) {
+ return t;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return ((ResourceConfig) super.configure()).register(new JettisonFeature());
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ super.configureClient(config);
+ config.register(new JettisonFeature());
+ config.register(MyJaxbContextResolver.class);
+ }
+
+ @Test
+ public void testStringCharsetResource() {
+ String in = "\u00A9 CONTENT \u00FF \u2200 \u22FF";
+
+ WebTarget t = target().path("StringCharsetResource");
+
+ for (String charset : CHARSETS) {
+ Response r = t.path(charset).request().post(Entity.entity(in, "text/plain;charset=" + charset));
+
+ byte[] inBytes = getRequestEntity();
+ byte[] outBytes = getEntityAsByteArray(r);
+
+ _verify(inBytes, outBytes);
+ }
+ }
+
+ public abstract static class CharsetResource<T> {
+
+ @Context
+ HttpHeaders h;
+
+ @POST
+ @Produces("application/*")
+ public Response post(T t) {
+ return Response.ok(t, h.getMediaType()).build();
+ }
+ }
+
+ @Path("/StringResource")
+ public static class StringResource extends CharsetResource<String> {
+
+ }
+
+ @Test
+ public void testStringRepresentation() {
+ _test(CONTENT, StringResource.class);
+ }
+
+ @Path("/FormMultivaluedMapResource")
+ public static class FormMultivaluedMapResource extends CharsetResource<MultivaluedMap<String, String>> {
+
+ }
+
+ @Test
+ public void testFormMultivaluedMapRepresentation() {
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+
+ map.add("name", "\u00A9 CONTENT \u00FF \u2200 \u22FF");
+ map.add("name", "� � �");
+ _test(map, FormMultivaluedMapResource.class, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
+ }
+
+ @Path("/FormResource")
+ public static class FormResource extends CharsetResource<Form> {
+
+ }
+
+ @Test
+ public void testRepresentation() {
+ Form form = new Form();
+
+ form.param("name", "\u00A9 CONTENT \u00FF \u2200 \u22FF");
+ form.param("name", "� � �");
+ _test(form, FormResource.class, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
+ }
+
+ @Path("/JSONObjectResource")
+ public static class JSONObjectResource extends CharsetResource<JSONObject> {
+
+ }
+
+ @Test
+ public void testJSONObjectRepresentation() throws Exception {
+ JSONObject object = new JSONObject();
+ object.put("userid", 1234)
+ .put("username", CONTENT)
+ .put("email", "a@b")
+ .put("password", "****");
+
+ _test(object, JSONObjectResource.class, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Path("/JSONOArrayResource")
+ public static class JSONOArrayResource extends CharsetResource<JSONArray> {
+
+ }
+
+ @Test
+ public void testJSONArrayRepresentation() throws Exception {
+ JSONArray array = new JSONArray();
+ array.put(CONTENT).put("Two").put("Three").put(1).put(2.0);
+
+ _test(array, JSONOArrayResource.class, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Path("/JAXBBeanResource")
+ public static class JAXBBeanResource extends CharsetResource<JaxbBean> {
+
+ }
+
+ @Test
+ public void testJAXBBeanXMLRepresentation() {
+ _test(new JaxbBean(CONTENT), JAXBBeanResource.class, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Test
+ public void testJAXBBeanJSONRepresentation() {
+ _test(new JaxbBean(CONTENT), JAXBBeanResource.class, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Provider
+ public static class MyJaxbContextResolver implements ContextResolver<JAXBContext> {
+
+ JAXBContext context;
+
+ public MyJaxbContextResolver() throws Exception {
+ context = new JettisonJaxbContext(JaxbBean.class);
+ }
+
+ public JAXBContext getContext(Class<?> objectType) {
+ return (objectType == JaxbBean.class) ? context : null;
+ }
+ }
+
+ @Test
+ public void testJAXBBeanJSONRepresentationWithContextResolver() throws Exception {
+ JaxbBean in = new JaxbBean(CONTENT);
+ WebTarget t = target("/JAXBBeanResource");
+ for (String charset : CHARSETS) {
+ Response rib = t.request().post(Entity.entity(in, "application/json;charset=" + charset));
+ byte[] inBytes = getRequestEntity();
+ byte[] outBytes = getEntityAsByteArray(rib);
+ _verify(inBytes, outBytes);
+ }
+ }
+
+ @Path("/ReaderResource")
+ public static class ReaderResource extends CharsetResource<Reader> {
+
+ }
+
+ @Test
+ public void testReaderRepresentation() throws Exception {
+ WebTarget t = target("/ReaderResource");
+ for (String charset : CHARSETS) {
+ Response rib = t.request().post(Entity.entity(new StringReader(CONTENT), "text/plain;charset=" + charset));
+ byte[] inBytes = getRequestEntity();
+ byte[] outBytes = getEntityAsByteArray(rib);
+ _verify(inBytes, outBytes);
+ }
+ }
+
+ @Override
+ public <T> void _test(T in, Class resource) {
+ _test(in, resource, MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ @Override
+ public <T> void _test(T in, Class resource, MediaType m) {
+ WebTarget t = target(resource.getSimpleName());
+ for (String charset : CHARSETS) {
+ Map<String, String> p = new HashMap<>();
+ p.put("charset", charset);
+ MediaType _m = new MediaType(m.getType(), m.getSubtype(), p);
+ Response rib = t.request().post(Entity.entity(in, _m));
+ byte[] inBytes = getRequestEntity();
+ byte[] outBytes = getEntityAsByteArray(rib);
+ _verify(inBytes, outBytes);
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ContextResolverMediaTypeTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ContextResolverMediaTypeTest.java
new file mode 100644
index 0000000..e9250e3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ContextResolverMediaTypeTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+@RunWith(Enclosed.class)
+public class ContextResolverMediaTypeTest {
+
+ @Produces("text/plain")
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class TextPlainContextResolver implements ContextResolver<String> {
+
+ public String getContext(Class<?> objectType) {
+ return "text/plain";
+ }
+ }
+
+ @Produces("text/*")
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class TextContextResolver implements ContextResolver<String> {
+
+ public String getContext(Class<?> objectType) {
+ return "text/*";
+ }
+ }
+
+ @Produces("*/*")
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class WildcardContextResolver implements ContextResolver<String> {
+
+ public String getContext(Class<?> objectType) {
+ return "*/*";
+ }
+ }
+
+ @Produces({"text/plain", "text/html"})
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class TextPlainHtmlContextResolver implements ContextResolver<String> {
+
+ public String getContext(Class<?> objectType) {
+ return "text/plain/html";
+ }
+
+ }
+
+ @Produces("text/html")
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class TextHtmlContextResolver implements ContextResolver<String> {
+
+ public String getContext(Class<?> objectType) {
+ return "text/html";
+ }
+
+ }
+
+ @Path("/")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class ContextResource {
+
+ @Context
+ Providers p;
+
+ @Context
+ ContextResolver<String> cr;
+
+ @GET
+ @Path("{id: .+}")
+ public String get(@PathParam("id") MediaType m) {
+ ContextResolver<String> cr = p.getContextResolver(String.class, m);
+
+ // Verify cache is working
+ ContextResolver<String> cachedCr = p.getContextResolver(String.class, m);
+ assertEquals(cr, cachedCr);
+
+ if (cr == null) {
+ return "NULL";
+ } else {
+ return cr.getContext(null);
+ }
+ }
+ }
+
+ public static class ProduceTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ContextResource.class,
+ TextPlainContextResolver.class,
+ TextContextResolver.class,
+ WildcardContextResolver.class);
+ }
+
+ @Test
+ public void testProduce() throws IOException {
+
+ WebTarget target = target();
+
+ assertEquals("text/plain", target.path("text/plain").request().get(String.class));
+ assertEquals("text/*", target.path("text/*").request().get(String.class));
+ assertEquals("*/*", target.path("*/*").request().get(String.class));
+
+ assertEquals("text/*", target.path("text/html").request().get(String.class));
+
+ assertEquals("*/*", target.path("application/xml").request().get(String.class));
+ assertEquals("*/*", target.path("application/*").request().get(String.class));
+ }
+ }
+
+ public static class ProducesTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ContextResource.class,
+ TextPlainHtmlContextResolver.class,
+ TextContextResolver.class,
+ WildcardContextResolver.class);
+ }
+
+ @Test
+ public void testProduces() throws IOException {
+ WebTarget target = target();
+
+ assertEquals("text/plain/html", target.path("text/plain").request().get(String.class));
+ assertEquals("text/plain/html", target.path("text/html").request().get(String.class));
+ assertEquals("text/*", target.path("text/*").request().get(String.class));
+ assertEquals("*/*", target.path("*/*").request().get(String.class));
+
+ assertEquals("text/*", target.path("text/csv").request().get(String.class));
+
+ assertEquals("*/*", target.path("application/xml").request().get(String.class));
+ assertEquals("*/*", target.path("application/*").request().get(String.class));
+ }
+ }
+
+ public static class ProducesSeparateTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ContextResource.class,
+ TextPlainContextResolver.class,
+ TextHtmlContextResolver.class,
+ TextContextResolver.class,
+ WildcardContextResolver.class);
+ }
+
+ @Test
+ public void testProducesSeparate() throws IOException {
+ WebTarget target = target();
+
+ assertEquals("text/plain", target.path("text/plain").request().get(String.class));
+ assertEquals("text/html", target.path("text/html").request().get(String.class));
+ assertEquals("text/*", target.path("text/*").request().get(String.class));
+ assertEquals("*/*", target.path("*/*").request().get(String.class));
+
+ assertEquals("text/*", target.path("text/csv").request().get(String.class));
+
+ assertEquals("*/*", target.path("application/xml").request().get(String.class));
+ assertEquals("*/*", target.path("application/*").request().get(String.class));
+ }
+ }
+
+ public static class ProducesXXXTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ContextResource.class,
+ TextPlainContextResolver.class,
+ TextHtmlContextResolver.class);
+ }
+
+ @Test
+ public void testProducesXXX() throws IOException {
+ WebTarget target = target();
+
+ assertEquals("text/plain", target.path("text/plain").request().get(String.class));
+ assertEquals("text/html", target.path("text/html").request().get(String.class));
+ assertEquals("NULL", target.path("text/*").request().get(String.class));
+ assertEquals("NULL", target.path("*/*").request().get(String.class));
+
+ assertEquals("NULL", target.path("text/csv").request().get(String.class));
+
+ assertEquals("NULL", target.path("application/xml").request().get(String.class));
+ assertEquals("NULL", target.path("application/*").request().get(String.class));
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyEntityTest.java
new file mode 100644
index 0000000..3624e43
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyEntityTest.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.ResponseProcessingException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NoContentException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * JERSEY-1540.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class EmptyEntityTest extends AbstractTypeTester {
+
+ public static class TestEmtpyBean {
+ private final String value;
+
+ public TestEmtpyBean(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ @Provider
+ public static class TestEmptyBeanProvider implements MessageBodyReader<TestEmtpyBean>, MessageBodyWriter<TestEmtpyBean> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return TestEmtpyBean.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public TestEmtpyBean readFrom(Class<TestEmtpyBean> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ final String value = ReaderWriter.readFromAsString(entityStream, mediaType);
+ return new TestEmtpyBean(value);
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return TestEmtpyBean.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(TestEmtpyBean testEmtpyBean,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(TestEmtpyBean testEmtpyBean,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ ReaderWriter.writeToAsString(testEmtpyBean.getValue(), entityStream, mediaType);
+ }
+ }
+
+ @XmlRootElement
+ public static class TestJaxbBean {
+
+ }
+
+ @Path("empty")
+ public static class EmptyResource {
+
+ @POST
+ @Path("jaxbelem")
+ public String jaxbelem(JAXBElement<String> jaxb) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("jaxbbean")
+ public String jaxbbean(TestJaxbBean bean) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("jaxblist")
+ public String jaxblist(List<TestJaxbBean> beans) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("boolean")
+ public String bool(Boolean b) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("character")
+ public String character(Character c) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("integer")
+ public String integer(Integer i) {
+ return "ERROR"; // shouldn't be called
+ }
+
+ @POST
+ @Path("emptybean")
+ public String emptyBean(TestEmtpyBean bean) {
+ return (bean.getValue().isEmpty()) ? "PASSED" : "ERROR";
+ }
+
+ @GET
+ @Path("getempty")
+ public Response getEmpty(@Context HttpHeaders headers) {
+ return Response.ok().type(headers.getAcceptableMediaTypes().get(0)).header(HttpHeaders.CONTENT_LENGTH, 0).build();
+ }
+ }
+
+ public EmptyEntityTest() {
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testSendEmptyJAXBElement() {
+ WebTarget target = target("empty/jaxbelem");
+ final Response response = target.request().post(Entity.entity(null, MediaType.APPLICATION_XML_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyJAXBbean() {
+ WebTarget target = target("empty/jaxbbean");
+ final Response response = target.request().post(Entity.entity(null, MediaType.APPLICATION_XML_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyJAXBlist() {
+ WebTarget target = target("empty/jaxblist");
+ final Response response = target.request().post(Entity.entity(null, MediaType.APPLICATION_XML_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyBoolean() {
+ WebTarget target = target("empty/boolean");
+ final Response response = target.request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyCharacter() {
+ WebTarget target = target("empty/character");
+ final Response response = target.request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyInteger() {
+ WebTarget target = target("empty/integer");
+ final Response response = target.request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testSendEmptyBean() {
+ WebTarget target = target("empty/emptybean");
+ final Response response = target.request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("PASSED", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testReceiveEmptyJAXBElement() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("application/xml").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(new GenericType<JAXBElement<String>>() {
+ });
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("application/xml").get(new GenericType<JAXBElement<String>>() {
+ });
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyJAXBbean() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("application/xml").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(TestJaxbBean.class);
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("application/xml").get(TestJaxbBean.class);
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyJAXBlist() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("application/xml").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(new GenericType<List<TestJaxbBean>>() {
+ });
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("application/xml").get(new GenericType<List<TestJaxbBean>>() {
+ });
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyBoolean() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("text/plain").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(Boolean.class);
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("text/plain").get(Boolean.class);
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyCharacter() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("text/plain").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(Character.class);
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("text/plain").get(Character.class);
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyInteger() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("text/plain").get();
+ assertEquals(200, response.getStatus());
+
+ try {
+ response.readEntity(Integer.class);
+ fail("ProcessingException expected.");
+ } catch (ProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+
+ try {
+ target.request("text/plain").get(Integer.class);
+ fail("ResponseProcessingException expected.");
+ } catch (ResponseProcessingException ex) {
+ assertSame(NoContentException.class, ex.getCause().getClass());
+ }
+ }
+
+ @Test
+ public void testReceiveEmptyBean() {
+ WebTarget target = target("empty/getempty");
+ final Response response = target.request("text/plain").get();
+ assertEquals(200, response.getStatus());
+
+ assertTrue(response.readEntity(TestEmtpyBean.class).getValue().isEmpty());
+ assertTrue(target.request("text/plain").get(TestEmtpyBean.class).getValue().isEmpty());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestToEntityParamTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestToEntityParamTest.java
new file mode 100644
index 0000000..46258b6
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestToEntityParamTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test for JERSEY-1579.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EmptyRequestToEntityParamTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(EntityResource.class);
+ }
+
+ @Path("/")
+ public static class EntityResource {
+
+ @DELETE
+ public void delete(Map<String, String> entity) {
+ Assert.assertNull(entity);
+ }
+ }
+
+ @Test
+ public void testEmptyRequest() {
+ Response response = target().request().delete(Response.class);
+ Assert.assertEquals(204, response.getStatus());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestWithJaxbTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestWithJaxbTest.java
new file mode 100644
index 0000000..a7c4f0d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EmptyRequestWithJaxbTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jettison.JettisonConfig;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.jettison.JettisonJaxbContext;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+@RunWith(Enclosed.class)
+public class EmptyRequestWithJaxbTest {
+
+ @SuppressWarnings("UnusedParameters")
+ @Path("/")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class Resource {
+
+ @POST
+ public void bean(JaxbBean b) {
+ }
+
+ @Path("type")
+ @POST
+ public void type(JaxbBeanType b) {
+ }
+
+ @Path("list-bean")
+ @POST
+ public void listBean(List<JaxbBean> b) {
+ }
+
+ @Path("list-type")
+ @POST
+ public void listType(List<JaxbBeanType> b) {
+ }
+
+ @Path("array-bean")
+ @POST
+ public void arrayBean(JaxbBean[] b) {
+ }
+
+ @Path("array-type")
+ @POST
+ public void arrayType(JaxbBeanType[] b) {
+ }
+
+ }
+
+ public static class EmptyRequestTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class).register(new JettisonFeature());
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(JettisonFeature.class);
+ }
+
+ @Test
+ public void testEmptyJsonRequestMapped() {
+ _test(target());
+ }
+
+ @Test
+ public void testEmptyXmlRequest() {
+ WebTarget r = target();
+
+ Response cr = r.request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+
+ cr = r.path("type").request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+
+ cr = r.path("list-bean").request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+
+ cr = r.path("list-type").request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+
+ cr = r.path("array-bean").request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+
+ cr = r.path("array-type").request().post(Entity.entity(null, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+ }
+
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public abstract static class CR implements ContextResolver<JAXBContext> {
+
+ private final JAXBContext context;
+
+ private final Class[] classes = {JaxbBean.class, JaxbBeanType.class};
+
+ private final Set<Class> types = new HashSet<>(Arrays.asList(classes));
+
+ public CR() {
+ try {
+ context = configure(classes);
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ protected abstract JAXBContext configure(Class[] classes) throws JAXBException;
+
+ public JAXBContext getContext(Class<?> objectType) {
+ return (types.contains(objectType)) ? context : null;
+ }
+ }
+
+ public static class MappedJettisonCRTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MappedJettisonCR.class, Resource.class).register(new JettisonFeature());
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(JettisonFeature.class);
+ }
+
+ public static class MappedJettisonCR extends CR {
+
+ protected JAXBContext configure(Class[] classes) throws JAXBException {
+ return new JettisonJaxbContext(JettisonConfig.mappedJettison().build(), classes);
+ }
+ }
+
+ @Test
+ public void testMappedJettisonCR() {
+ _test(target());
+ }
+ }
+
+ public static class BadgerFishCRTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(BadgerFishCR.class, Resource.class).register(new JettisonFeature());
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(JettisonFeature.class);
+ }
+
+ public static class BadgerFishCR extends CR {
+
+ protected JAXBContext configure(Class[] classes) throws JAXBException {
+ return new JettisonJaxbContext(JettisonConfig.badgerFish().build(), classes);
+ }
+ }
+
+ @Test
+ public void testBadgerFishCR() {
+ _test(target());
+ }
+ }
+
+ public static void _test(WebTarget target) {
+ Response cr = target.request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+
+ cr = target.path("type").request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+
+ cr = target.path("list-bean").request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+
+ cr = target.path("list-type").request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+
+ cr = target.path("array-bean").request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+
+ cr = target.path("array-type").request().post(Entity.entity(null, "application/json"));
+ assertEquals(400, cr.getStatus());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
new file mode 100644
index 0000000..39ed8f2
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
@@ -0,0 +1,1166 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.activation.DataSource;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.message.internal.FileProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+@RunWith(ConcurrentRunner.class)
+public class EntityTypesTest extends AbstractTypeTester {
+
+ @Path("InputStreamResource")
+ public static class InputStreamResource {
+
+ @POST
+ public InputStream post(final InputStream in) throws IOException {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int read;
+ final byte[] data = new byte[2048];
+ while ((read = in.read(data)) != -1) {
+ out.write(data, 0, read);
+ }
+
+ return new ByteArrayInputStream(out.toByteArray());
+ }
+ }
+
+ @Test
+ public void testInputStream() {
+ final ByteArrayInputStream in = new ByteArrayInputStream("CONTENT".getBytes());
+ _test(in, InputStreamResource.class);
+ }
+
+ @Path("StringResource")
+ public static class StringResource extends AResource<String> {
+ }
+
+ @Test
+ public void testString() {
+ _test("CONTENT", StringResource.class);
+ }
+
+ @Path("DataSourceResource")
+ public static class DataSourceResource extends AResource<DataSource> {
+ }
+
+ @Path("ByteArrayResource")
+ public static class ByteArrayResource extends AResource<byte[]> {
+ }
+
+ @Test
+ public void testByteArrayRepresentation() {
+ _test("CONTENT".getBytes(), ByteArrayResource.class);
+ }
+
+ @Path("JaxbBeanResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JaxbBeanResource extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentation() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanResource.class, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Path("JaxbBeanResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JaxbBeanResourceMediaType extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationMediaType() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationError() {
+ final WebTarget target = target("JaxbBeanResource");
+
+ final String xml = "<root>foo</root>";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JaxbBeanTextResource")
+ @Produces("text/xml")
+ @Consumes("text/xml")
+ public static class JaxbBeanTextResource extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanTextRepresentation() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanTextResource.class, MediaType.TEXT_XML_TYPE);
+ }
+
+ @Path("JAXBElementBeanResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBElementBeanResource extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentation() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanResource.class, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Path("JAXBElementListResource")
+ @Produces({"application/xml", "application/json"})
+ @Consumes({"application/xml", "application/json"})
+ public static class JAXBElementListResource extends AResource<List<JAXBElement<String>>> {
+ }
+
+ private List<JAXBElement<String>> getJAXBElementList() {
+ return Arrays.asList(getJAXBElementArray());
+ }
+
+ @Test
+ public void testJAXBElementListXMLRepresentation() {
+ _testListOrArray(true, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ public void _testListOrArray(final boolean isList, final MediaType mt) {
+ final Object in = isList ? getJAXBElementList() : getJAXBElementArray();
+ final GenericType gt = isList ? new GenericType<List<JAXBElement<String>>>() {
+ } : new GenericType<JAXBElement<String>[]>() {
+ };
+
+ final WebTarget target = target(isList ? "JAXBElementListResource" : "JAXBElementArrayResource");
+ final Object out = target.request(mt).post(Entity.entity(new GenericEntity(in, gt.getType()), mt), gt);
+
+ final List<JAXBElement<String>> inList = isList ? ((List<JAXBElement<String>>) in) : Arrays
+ .asList((JAXBElement<String>[]) in);
+ final List<JAXBElement<String>> outList = isList ? ((List<JAXBElement<String>>) out) : Arrays
+ .asList((JAXBElement<String>[]) out);
+ assertEquals("Lengths differ", inList.size(), outList.size());
+ for (int i = 0; i < inList.size(); i++) {
+ assertEquals("Names of elements at index " + i + " differ", inList.get(i).getName(), outList.get(i).getName());
+ assertEquals("Values of elements at index " + i + " differ", inList.get(i).getValue(), outList.get(i).getValue());
+ }
+ }
+
+ @Test
+ public void testJAXBElementListJSONRepresentation() {
+ _testListOrArray(true, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Path("JAXBElementArrayResource")
+ @Produces({"application/xml", "application/json"})
+ @Consumes({"application/xml", "application/json"})
+ public static class JAXBElementArrayResource extends AResource<JAXBElement<String>[]> {
+ }
+
+ private JAXBElement<String>[] getJAXBElementArray() {
+ return new JAXBElement[] {
+ new JAXBElement(QName.valueOf("element1"), String.class, "ahoj"),
+ new JAXBElement(QName.valueOf("element2"), String.class, "nazdar")
+ };
+ }
+
+ @Test
+ public void testJAXBElementArrayXMLRepresentation() {
+ _testListOrArray(false, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Test
+ public void testJAXBElementArrayJSONRepresentation() {
+ _testListOrArray(false, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Path("JAXBElementBeanResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBElementBeanResourceMediaType extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationMediaType() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationError() {
+ final WebTarget target = target("JAXBElementBeanResource");
+
+ final String xml = "<root><value>foo";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JAXBElementBeanTextResource")
+ @Produces("text/xml")
+ @Consumes("text/xml")
+ public static class JAXBElementBeanTextResource extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanTextRepresentation() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanTextResource.class, MediaType.TEXT_XML_TYPE);
+ }
+
+ @Path("JaxbBeanResourceAtom")
+ @Produces("application/atom+xml")
+ @Consumes("application/atom+xml")
+ public static class JaxbBeanResourceAtom extends AResource<JAXBElement<JaxbBean>> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationMediaTypeAtom() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanResourceAtom.class, MediaType.valueOf("application/atom+xml"));
+ }
+
+ @Path("JAXBTypeResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBTypeResource {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return ((ResourceConfig) super.configure()).register(new JettisonFeature());
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+ config.register(new JettisonFeature());
+ }
+
+ @Test
+ public void testJAXBTypeRepresentation() {
+ final WebTarget target = target("JAXBTypeResource");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/xml"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBTypeResourceMediaType extends JAXBTypeResource {
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationMediaType() {
+ final WebTarget target = target("JAXBTypeResourceMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBObjectResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBObjectResource {
+
+ @POST
+ public Object post(final Object o) {
+ return o;
+ }
+ }
+
+ @Provider
+ public static class JAXBObjectResolver implements ContextResolver<JAXBContext> {
+
+ public JAXBContext getContext(final Class<?> c) {
+ if (Object.class == c) {
+ try {
+ return JAXBContext.newInstance(JaxbBean.class);
+ } catch (final JAXBException ex) {
+ }
+ }
+ return null;
+ }
+ }
+
+ @Test
+ public void testJAXBObjectRepresentation() {
+ final WebTarget target = target("JAXBObjectResource");
+ final Object in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/xml"), JaxbBean.class);
+ assertEquals(in, out);
+ }
+
+ @Path("JAXBObjectResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBObjectResourceMediaType extends JAXBObjectResource {
+ }
+
+ @Test
+ public void testJAXBObjectRepresentationMediaType() {
+ final WebTarget target = target("JAXBObjectResourceMediaType");
+ final Object in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBean.class);
+ assertEquals(in, out);
+ }
+
+ @Test
+ public void testJAXBObjectRepresentationError() {
+ final WebTarget target = target("JAXBObjectResource");
+
+ final String xml = "<root>foo</root>";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("FileResource")
+ public static class FileResource extends AResource<File> {
+ }
+
+ @Test
+ public void testFileRepresentation() throws IOException {
+ final FileProvider fp = new FileProvider();
+ final File in = fp.readFrom(File.class, File.class, null, null, null,
+ new ByteArrayInputStream("CONTENT".getBytes()));
+
+ _test(in, FileResource.class);
+ }
+
+ @Produces("application/x-www-form-urlencoded")
+ @Consumes("application/x-www-form-urlencoded")
+ @Path("FormResource")
+ public static class FormResource extends AResource<Form> {
+ }
+
+ @Test
+ public void testFormRepresentation() {
+ final Form fp = new Form();
+ fp.param("Email", "johndoe@gmail.com");
+ fp.param("Passwd", "north 23AZ");
+ fp.param("service", "cl");
+ fp.param("source", "Gulp-CalGul-1.05");
+
+ final WebTarget target = target("FormResource");
+ final Form response = target.request().post(Entity.entity(fp, MediaType.APPLICATION_FORM_URLENCODED_TYPE), Form.class);
+
+ assertEquals(fp.asMap().size(), response.asMap().size());
+ for (final Map.Entry<String, List<String>> entry : fp.asMap().entrySet()) {
+ final List<String> s = response.asMap().get(entry.getKey());
+ assertEquals(entry.getValue().size(), s.size());
+ for (Iterator<String> it1 = entry.getValue().listIterator(), it2 = s.listIterator(); it1.hasNext(); ) {
+ assertEquals(it1.next(), it2.next());
+ }
+ }
+ }
+
+ @Produces("application/json")
+ @Consumes("application/json")
+ @Path("JSONObjectResource")
+ public static class JSONObjectResource extends AResource<JSONObject> {
+ }
+
+ @Test
+ public void testJSONObjectRepresentation() throws Exception {
+ final JSONObject object = new JSONObject();
+ object.put("userid", 1234)
+ .put("username", "1234")
+ .put("email", "a@b")
+ .put("password", "****");
+
+ _test(object, JSONObjectResource.class, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Produces("application/xxx+json")
+ @Consumes("application/xxx+json")
+ @Path("JSONObjectResourceGeneralMediaType")
+ public static class JSONObjectResourceGeneralMediaType extends AResource<JSONObject> {
+ }
+
+ @Test
+ public void testJSONObjectRepresentationGeneralMediaTyp() throws Exception {
+ final JSONObject object = new JSONObject();
+ object.put("userid", 1234)
+ .put("username", "1234")
+ .put("email", "a@b")
+ .put("password", "****");
+
+ _test(object, JSONObjectResourceGeneralMediaType.class, MediaType.valueOf("application/xxx+json"));
+ }
+
+ @Produces("application/json")
+ @Consumes("application/json")
+ @Path("JSONOArrayResource")
+ public static class JSONOArrayResource extends AResource<JSONArray> {
+ }
+
+ @Test
+ public void testJSONArrayRepresentation() throws Exception {
+ final JSONArray array = new JSONArray();
+ array.put("One").put("Two").put("Three").put(1).put(2.0);
+
+ _test(array, JSONOArrayResource.class, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Produces("application/xxx+json")
+ @Consumes("application/xxx+json")
+ @Path("JSONOArrayResourceGeneralMediaType")
+ public static class JSONOArrayResourceGeneralMediaType extends AResource<JSONArray> {
+ }
+
+ @Test
+ public void testJSONArrayRepresentationGeneralMediaType() throws Exception {
+ final JSONArray array = new JSONArray();
+ array.put("One").put("Two").put("Three").put(1).put(2.0);
+
+ _test(array, JSONOArrayResourceGeneralMediaType.class, MediaType.valueOf("application/xxx+json"));
+ }
+
+ // @Path("FeedResource")
+ // public static class FeedResource extends AResource<Feed> {
+ // }
+ //
+ // @Test
+ // public void testFeedRepresentation() throws Exception {
+ // InputStream in = this.getClass().getResourceAsStream("feed.xml");
+ // AtomFeedProvider afp = new AtomFeedProvider();
+ // Feed f = afp.readFrom(Feed.class, Feed.class, null, null, null, in);
+ //
+ // _test(f, FeedResource.class);
+ // }
+ //
+ // @Path("EntryResource")
+ // public static class EntryResource extends AResource<Entry> {
+ // }
+ //
+ // @Test
+ // public void testEntryRepresentation() throws Exception {
+ // InputStream in = this.getClass().getResourceAsStream("entry.xml");
+ // AtomEntryProvider afp = new AtomEntryProvider();
+ // Entry e = afp.readFrom(Entry.class, Entry.class, null, null, null, in);
+ //
+ // _test(e, EntryResource.class);
+ // }
+
+ @Path("ReaderResource")
+ public static class ReaderResource extends AResource<Reader> {
+ }
+
+ @Test
+ public void testReaderRepresentation() throws Exception {
+ _test(new StringReader("CONTENT"), ReaderResource.class);
+ }
+
+ private static final String XML_DOCUMENT = "<n:x xmlns:n=\"urn:n\"><n:e>CONTNET</n:e></n:x>";
+
+ @Path("StreamSourceResource")
+ public static class StreamSourceResource extends AResource<StreamSource> {
+ }
+
+ @Test
+ public void testStreamSourceRepresentation() throws Exception {
+ final StreamSource ss = new StreamSource(
+ new ByteArrayInputStream(XML_DOCUMENT.getBytes()));
+ _test(ss, StreamSourceResource.class);
+ }
+
+ @Path("SAXSourceResource")
+ public static class SAXSourceResource extends AResource<SAXSource> {
+ }
+
+ @Test
+ public void testSAXSourceRepresentation() throws Exception {
+ final StreamSource ss = new StreamSource(
+ new ByteArrayInputStream(XML_DOCUMENT.getBytes()));
+ _test(ss, SAXSourceResource.class);
+ }
+
+ @Path("DOMSourceResource")
+ public static class DOMSourceResource extends AResource<DOMSource> {
+ }
+
+ @Test
+ public void testDOMSourceRepresentation() throws Exception {
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ final Document d = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(XML_DOCUMENT)));
+ final DOMSource ds = new DOMSource(d);
+ _test(ds, DOMSourceResource.class);
+ }
+
+ @Path("DocumentResource")
+ public static class DocumentResource extends AResource<Document> {
+ }
+
+ @Test
+ public void testDocumentRepresentation() throws Exception {
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ final Document d = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(XML_DOCUMENT)));
+ _test(d, DocumentResource.class);
+ }
+
+ @Path("FormMultivaluedMapResource")
+ @Produces("application/x-www-form-urlencoded")
+ @Consumes("application/x-www-form-urlencoded")
+ public static class FormMultivaluedMapResource {
+
+ @POST
+ public MultivaluedMap<String, String> post(final MultivaluedMap<String, String> t) {
+ return t;
+ }
+ }
+
+ @Test
+ public void testFormMultivaluedMapRepresentation() {
+ final MultivaluedMap<String, String> fp = new MultivaluedStringMap();
+ fp.add("Email", "johndoe@gmail.com");
+ fp.add("Passwd", "north 23AZ");
+ fp.add("service", "cl");
+ fp.add("source", "Gulp-CalGul-1.05");
+ fp.add("source", "foo.java");
+ fp.add("source", "bar.java");
+
+ final WebTarget target = target("FormMultivaluedMapResource");
+ final MultivaluedMap _fp = target.request()
+ .post(Entity.entity(fp, "application/x-www-form-urlencoded"), MultivaluedMap.class);
+ assertEquals(fp, _fp);
+ }
+
+ @Path("StreamingOutputResource")
+ public static class StreamingOutputResource {
+
+ @GET
+ public StreamingOutput get() {
+ return new StreamingOutput() {
+ public void write(final OutputStream entity) throws IOException {
+ entity.write("CONTENT".getBytes());
+ }
+ };
+ }
+ }
+
+ @Test
+ public void testStreamingOutputRepresentation() throws Exception {
+ final WebTarget target = target("StreamingOutputResource");
+ assertEquals("CONTENT", target.request().get(String.class));
+ }
+
+ @Path("JAXBElementBeanJSONResource")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class JAXBElementBeanJSONResource extends AResource<JAXBElement<String>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanJSONRepresentation() {
+ final WebTarget target = target("JAXBElementBeanJSONResource");
+
+ final Response rib = target.request().post(
+ Entity.entity(new JAXBElement<>(new QName("test"), String.class, "CONTENT"), "application/json"));
+
+ // TODO: the following would not be needed if i knew how to workaround JAXBElement<String>.class literal
+
+ final byte[] inBytes = getRequestEntity();
+ final byte[] outBytes = getEntityAsByteArray(rib);
+
+ assertEquals(new String(outBytes), inBytes.length, outBytes.length);
+ for (int i = 0; i < inBytes.length; i++) {
+ if (inBytes[i] != outBytes[i]) {
+ assertEquals("Index: " + i, inBytes[i], outBytes[i]);
+ }
+ }
+ }
+
+ @Path("JaxbBeanResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JaxbBeanResourceJSON extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationJSON() {
+ final WebTarget target = target("JaxbBeanResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JaxbBeanResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JaxbBeanResourceJSONMediaType extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationJSONMediaType() {
+ final WebTarget target = target("JaxbBeanResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBElementBeanResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBElementBeanResourceJSON extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationJSON() {
+ final WebTarget target = target("JAXBElementBeanResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBElementBeanResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBElementBeanResourceJSONMediaType extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationJSONMediaType() {
+ final WebTarget target = target("JAXBElementBeanResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBTypeResourceJSON {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationJSON() {
+ final WebTarget target = target("JAXBTypeResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/json"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBTypeResourceJSONMediaType {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationJSONMediaType() {
+ final WebTarget target = target("JAXBTypeResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JaxbBeanResourceFastInfoset")
+ @Produces("application/fastinfoset")
+ @Consumes("application/fastinfoset")
+ public static class JaxbBeanResourceFastInfoset extends AResource<JaxbBean> {
+ }
+
+ @Test
+ @Ignore("TODO: unignore once fi support implemented (JERSEY-1190)")
+ // TODO: unignore once fi support implemented (JERSEY-1190)
+ public void testJaxbBeanRepresentationFastInfoset() {
+ final WebTarget target = target("JaxbBeanResourceFastInfoset");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/fastinfoset"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBElementBeanResourceFastInfoset")
+ @Produces("application/fastinfoset")
+ @Consumes("application/fastinfoset")
+ public static class JAXBElementBeanResourceFastInfoset extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ @Ignore("TODO: unignore once fi support implemented (JERSEY-1190)")
+ // TODO: unignore once fi support implemented (JERSEY-1190)
+ public void testJAXBElementBeanRepresentationFastInfoset() {
+ final WebTarget target = target("JAXBElementBeanResourceFastInfoset");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/fastinfoset"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceFastInfoset")
+ @Produces("application/fastinfoset")
+ @Consumes("application/fastinfoset")
+ public static class JAXBTypeResourceFastInfoset {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Test
+ @Ignore("TODO: unignore once fi support implemented (JERSEY-1190)")
+ // TODO: unignore once fi support implemented (JERSEY-1190)
+ public void testJAXBTypeRepresentationFastInfoset() {
+ final WebTarget target = target("JAXBTypeResourceFastInfoset");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/fastinfoset"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBListResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBListResource {
+
+ @POST
+ public List<JaxbBean> post(final List<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("set")
+ public Set<JaxbBean> postSet(final Set<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("queue")
+ public Queue<JaxbBean> postQueue(final Queue<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("stack")
+ public Stack<JaxbBean> postStack(final Stack<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("custom")
+ public MyArrayList<JaxbBean> postCustom(final MyArrayList<JaxbBean> l) {
+ return l;
+ }
+
+ @GET
+ public Collection<JaxbBean> get() {
+ final ArrayList<JaxbBean> l = new ArrayList<>();
+ l.add(new JaxbBean("one"));
+ l.add(new JaxbBean("two"));
+ l.add(new JaxbBean("three"));
+ return l;
+ }
+
+ @POST
+ @Path("type")
+ public List<JaxbBean> postType(final Collection<JaxbBeanType> l) {
+ final List<JaxbBean> beans = new ArrayList<>();
+ for (final JaxbBeanType t : l) {
+ beans.add(new JaxbBean(t.value));
+ }
+ return beans;
+ }
+ }
+
+ @Path("JAXBArrayResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBArrayResource {
+
+ @POST
+ public JaxbBean[] post(final JaxbBean[] l) {
+ return l;
+ }
+
+ @GET
+ public JaxbBean[] get() {
+ final ArrayList<JaxbBean> l = new ArrayList<>();
+ l.add(new JaxbBean("one"));
+ l.add(new JaxbBean("two"));
+ l.add(new JaxbBean("three"));
+ return l.toArray(new JaxbBean[l.size()]);
+ }
+
+ @POST
+ @Path("type")
+ public JaxbBean[] postType(final JaxbBeanType[] l) {
+ final List<JaxbBean> beans = new ArrayList<>();
+ for (final JaxbBeanType t : l) {
+ beans.add(new JaxbBean(t.value));
+ }
+ return beans.toArray(new JaxbBean[beans.size()]);
+ }
+ }
+
+ @Test
+ public void testJAXBArrayRepresentation() {
+ final WebTarget target = target("JAXBArrayResource");
+
+ final JaxbBean[] a = target.request().get(JaxbBean[].class);
+ JaxbBean[] b = target.request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
+ assertEquals(a.length, b.length);
+ for (int i = 0; i < a.length; i++) {
+ assertEquals(a[i], b[i]);
+ }
+
+ b = target.path("type").request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
+ assertEquals(a.length, b.length);
+ for (int i = 0; i < a.length; i++) {
+ assertEquals(a[i], b[i]);
+ }
+ }
+
+ @Path("JAXBListResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBListResourceMediaType extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationMediaType() {
+ final WebTarget target = target("JAXBListResourceMediaType");
+
+ Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request()
+ .post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+xml"),
+ new GenericType<Collection<JaxbBean>>() {
+ });
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+xml"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new LinkedList<>(a);
+ b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<Queue<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new HashSet<>(a);
+ b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<Set<JaxbBean>>() {
+ });
+ final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
+ @Override
+ public int compare(final JaxbBean t, final JaxbBean t1) {
+ return t.value.compareTo(t1.value);
+ }
+ };
+ final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
+ final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
+ t1.addAll(a);
+ t2.addAll(b);
+ assertEquals(t1, t2);
+
+ final Stack<JaxbBean> s = new Stack<>();
+ s.addAll(a);
+ b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
+ }, "application/foo+xml"), new GenericType<Stack<JaxbBean>>() {
+ });
+ assertEquals(s, b);
+
+ a = new MyArrayList<>(a);
+ b = target.path("custom").request()
+ .post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<MyArrayList<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testJAXBListRepresentationError() {
+ final WebTarget target = target("JAXBListResource");
+
+ final String xml = "<root><value>foo";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JAXBListResourceFastInfoset")
+ @Produces("application/fastinfoset")
+ @Consumes("application/fastinfoset")
+ public static class JAXBListResourceFastInfoset extends JAXBListResource {
+ }
+
+ /**
+ * TODO, the unmarshalling fails.
+ */
+ @Test
+ @Ignore("TODO: unignore once fi support implemented (JERSEY-1190)")
+ // TODO: unignore once fi support implemented (JERSEY-1190)
+ public void testJAXBListRepresentationFastInfoset() {
+ final WebTarget target = target("JAXBListResourceFastInfoset");
+
+ Collection<JaxbBean> a = target.request().get(new GenericType<Collection<JaxbBean>>() {
+ });
+
+ Collection<JaxbBean> b = target.request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/fastinfoset"), new GenericType<Collection<JaxbBean>>() {
+ }
+ );
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/fastinfoset"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new LinkedList<>(a);
+ b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
+ }, "application/fastinfoset"), new GenericType<Queue<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new HashSet<>(a);
+ b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
+ }, "application/fastinfoset"), new GenericType<Set<JaxbBean>>() {
+ });
+ final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
+ @Override
+ public int compare(final JaxbBean t, final JaxbBean t1) {
+ return t.value.compareTo(t1.value);
+ }
+ };
+ final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
+ final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
+ t1.addAll(a);
+ t2.addAll(b);
+ assertEquals(t1, t2);
+
+ final Stack<JaxbBean> s = new Stack<>();
+ s.addAll(a);
+ b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
+ }, "application/fastinfoset"), new GenericType<Stack<JaxbBean>>() {
+ });
+ assertEquals(s, b);
+
+ a = new MyArrayList<>(a);
+ b = target.path("custom").request()
+ .post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {
+ }, "application/fastinfoset"), new GenericType<MyArrayList<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+
+ @Path("JAXBListResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBListResourceJSON extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSON() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/json"), new GenericType<Collection<JaxbBean>>() {
+ });
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/json"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new LinkedList<>(a);
+ b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
+ }, "application/json"), new GenericType<Queue<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new HashSet<>(a);
+ b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
+ }, "application/json"), new GenericType<Set<JaxbBean>>() {
+ });
+ final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
+ @Override
+ public int compare(final JaxbBean t, final JaxbBean t1) {
+ return t.value.compareTo(t1.value);
+ }
+ };
+ final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
+ final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
+ t1.addAll(a);
+ t2.addAll(b);
+ assertEquals(t1, t2);
+
+ final Stack<JaxbBean> s = new Stack<>();
+ s.addAll(a);
+ b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
+ }, "application/json"), new GenericType<Stack<JaxbBean>>() {
+ });
+ assertEquals(s, b);
+
+ a = new MyArrayList<>(a);
+ b = target.path("custom").request()
+ .post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {
+ }, "application/json"), new GenericType<MyArrayList<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ // TODO: would be nice to produce/consume a real JSON array like following
+ // instead of what we have now:
+ // JSONArray a = r.get(JSONArray.class);
+ // JSONArray b = new JSONArray().
+ // put(new JSONObject().put("value", "one")).
+ // put(new JSONObject().put("value", "two")).
+ // put(new JSONObject().put("value", "three"));
+ // assertEquals(a.toString(), b.toString());
+ // JSONArray c = r.post(JSONArray.class, b);
+ // assertEquals(a.toString(), c.toString());
+ }
+
+ @Path("JAXBListResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBListResourceJSONMediaType extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONMediaType() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSONMediaType");
+
+ final Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+json"), new GenericType<Collection<JaxbBean>>() {
+ });
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+json"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ // TODO: would be nice to produce/consume a real JSON array like following
+ // instead of what we have now:
+ // JSONArray a = r.get(JSONArray.class);
+ // JSONArray b = new JSONArray().
+ // put(new JSONObject().put("value", "one")).
+ // put(new JSONObject().put("value", "two")).
+ // put(new JSONObject().put("value", "three"));
+ // assertEquals(a.toString(), b.toString());
+ // JSONArray c = r.post(JSONArray.class, b);
+ // assertEquals(a.toString(), c.toString());
+ }
+
+ @Path("/NoContentTypeJAXBResource")
+ public static class NoContentTypeJAXBResource {
+
+ @POST
+ public JaxbBean post(@Context final HttpHeaders headers, final JaxbBean bean) {
+ assertThat(headers.getMediaType(), is(MediaType.APPLICATION_XML_TYPE));
+ return bean;
+ }
+ }
+
+ @Test
+ public void testNoContentTypeJaxbEntity() throws IOException {
+ assertThat(target("NoContentTypeJAXBResource").request("application/xml").post(Entity.xml(new JaxbBean("foo")))
+ .getMediaType(),
+ is(MediaType.APPLICATION_XML_TYPE));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/GenericTypeAndEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/GenericTypeAndEntityTest.java
new file mode 100644
index 0000000..bed9281
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/GenericTypeAndEntityTest.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class GenericTypeAndEntityTest extends AbstractTypeTester {
+
+ @Provider
+ @SuppressWarnings("UnusedDeclaration")
+ public static class ListIntegerWriter implements MessageBodyReader<List<Integer>>, MessageBodyWriter<List<Integer>> {
+
+ private final Type t;
+
+ public ListIntegerWriter() {
+ final List<Integer> l = new ArrayList<>();
+ final GenericEntity<List<Integer>> ge = new GenericEntity<List<Integer>>(l) {};
+ this.t = ge.getType();
+ }
+
+ public boolean isWriteable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mt) {
+ return this.t.equals(t);
+ }
+
+ public long getSize(final List<Integer> l, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ public void writeTo(final List<Integer> l, final Class<?> c, final Type t, final Annotation[] as,
+ final MediaType mt, final MultivaluedMap<String, Object> hs,
+ final OutputStream out) throws IOException, WebApplicationException {
+ final StringBuilder sb = new StringBuilder();
+ for (final Integer i : l) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(i);
+ }
+ out.write(sb.toString().getBytes());
+ }
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return this.t.equals(genericType);
+ }
+
+ @Override
+ public List<Integer> readFrom(final Class<List<Integer>> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ return Arrays.stream(ReaderWriter.readFromAsString(entityStream, mediaType).split(","))
+ .map(input -> Integer.valueOf(input.trim()))
+ .collect(Collectors.toList());
+ }
+ }
+
+ public static class GenericListResource<T> {
+
+ @POST
+ @Path("genericType")
+ public List<T> post(final List<T> post) {
+ return post;
+ }
+ }
+
+ @Path("ListResource")
+ public static class ListResource extends GenericListResource<Integer> {
+
+ @GET
+ @Path("type")
+ public List<Integer> type() {
+ return Arrays.asList(1, 2, 3, 4);
+ }
+
+ @GET
+ @Path("genericEntity")
+ public GenericEntity<List<Integer>> genericEntity() {
+ return new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {};
+ }
+
+ @GET
+ @Path("object")
+ public Object object() {
+ return new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {};
+ }
+
+ @GET
+ @Path("response")
+ public Response response() {
+ return Response.ok(new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {}).build();
+ }
+
+ @GET
+ @Path("wrongGenericEntity")
+ public GenericEntity<List<Integer>> wrongGenericEntity() {
+ // wrongly constructed generic entity: generic type of the generic entity
+ // is not generic but just a List interface type. In this case
+ // the return generic type will be used
+ return new GenericEntity<>(Arrays.asList(1, 2, 3, 4), List.class);
+ }
+ }
+
+ public static class GenericListMediaTypeResource<T> {
+
+ @POST
+ @Path("genericType")
+ @Produces("text/plain")
+ public List<T> post(final List<T> post) {
+ return post;
+ }
+ }
+
+ @Path("ListResourceWithMediaType")
+ public static class ListResourceWithMediaType extends GenericListMediaTypeResource<Integer> {
+
+ @GET
+ @Path("type")
+ @Produces("text/plain")
+ public List<Integer> type() {
+ return Arrays.asList(1, 2, 3, 4);
+ }
+
+ @GET
+ @Path("genericEntity")
+ @Produces("text/plain")
+ public GenericEntity<List<Integer>> genericEntity() {
+ return new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {};
+ }
+
+ @GET
+ @Path("object")
+ @Produces("text/plain")
+ public Object object() {
+ return new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {};
+ }
+
+ @GET
+ @Path("response")
+ @Produces("text/plain")
+ public Response response() {
+ return Response.ok(new GenericEntity<List<Integer>>(Arrays.asList(1, 2, 3, 4)) {}).build();
+ }
+
+ @GET
+ @Path("wrongGenericEntity")
+ @Produces("text/plain")
+ public GenericEntity<List<Integer>> wrongGenericEntity() {
+ // wrongly constructed generic entity: generic type of the generic entity
+ // is not generic but just a List interface type. In this case
+ // the return generic type will be used
+ return new GenericEntity<>(Arrays.asList(1, 2, 3, 4), List.class);
+ }
+ }
+
+ @Test
+ public void testGenericType() {
+ _genericTest(ListResource.class);
+ }
+
+ @Test
+ public void testGenericTypeWithMediaType() {
+ _genericTest(ListResourceWithMediaType.class);
+ }
+
+ private void _genericTest(final Class resourceClass) {
+ final WebTarget target = target(resourceClass.getSimpleName());
+
+ _testPath(target, "type");
+ _testPath(target, "genericEntity");
+ _testPath(target, "object");
+ _testPath(target, "response");
+ _testPath(target, "wrongGenericEntity");
+
+ _testPathPost(target, "genericType");
+ }
+
+ private void _testPath(final WebTarget target, final String path) {
+ assertEquals("1, 2, 3, 4", target.path(path).request().get(String.class));
+ }
+
+ private void _testPathPost(final WebTarget target, final String path) {
+ assertEquals("1, 2, 3, 4", target.path(path).request().post(Entity.text("1, 2, 3, 4"), String.class));
+ }
+
+ @Provider
+ public static class MapStringReader implements MessageBodyReader<Map<String, String>>,
+ MessageBodyWriter<Map<String, String>> {
+
+ private final Type mapStringType;
+
+ public MapStringReader() {
+ final ParameterizedType iface = (ParameterizedType) this.getClass().getGenericInterfaces()[0];
+ mapStringType = iface.getActualTypeArguments()[0];
+ }
+
+ public boolean isReadable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mt) {
+ return Map.class == c && mapStringType.equals(t);
+ }
+
+ public Map<String, String> readFrom(final Class<Map<String, String>> c, final Type t, final Annotation[] as,
+ final MediaType mt, final MultivaluedMap<String, String> headers,
+ final InputStream in) throws IOException {
+ final String[] v = ReaderWriter.readFromAsString(in, mt).split(",");
+ final Map<String, String> m = new LinkedHashMap<>();
+ for (int i = 0; i < v.length; i = i + 2) {
+ m.put(v[i], v[i + 1]);
+ }
+ return m;
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mt) {
+ return Map.class.isAssignableFrom(c) && mapStringType.equals(t);
+ }
+
+ @Override
+ public long getSize(final Map<String, String> t, final Class<?> type, final Type genericType, final Annotation[] as,
+ final MediaType mt) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Map<String, String> t, final Class<?> c, final Type genericType, final Annotation[] as,
+ final MediaType mt, final MultivaluedMap<String, Object> hs,
+ final OutputStream out) throws IOException, WebApplicationException {
+ final StringBuilder sb = new StringBuilder();
+ for (final Map.Entry<String, String> e : t.entrySet()) {
+ if (sb.length() > 0) {
+ sb.append(',');
+ }
+ sb.append(e.getKey()).append(',').append(e.getValue());
+ }
+ out.write(sb.toString().getBytes());
+ }
+ }
+
+ public static class GenericMapResource<K, V> {
+
+ @POST
+ public Map<K, V> post(final Map<K, V> m) {
+ return m;
+ }
+ }
+
+ @Path("/MapResource")
+ public static class MapResource extends GenericMapResource<String, String> {
+
+ }
+
+ @Test
+ public void testGenericMap() throws Exception {
+ assertThat(target("/MapResource").request().post(Entity.text("a,b,c,d"), String.class), is("a,b,c,d"));
+ }
+
+ @Provider
+ public static class MapListStringReader implements MessageBodyReader<Map<String, List<String>>>,
+ MessageBodyWriter<Map<String, List<String>>> {
+
+ private final Type mapListStringType;
+
+ public MapListStringReader() {
+ final ParameterizedType iface = (ParameterizedType) this.getClass().getGenericInterfaces()[0];
+ mapListStringType = iface.getActualTypeArguments()[0];
+ }
+
+ public boolean isReadable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mt) {
+ return Map.class == c && mapListStringType.equals(t);
+ }
+
+ public Map<String, List<String>> readFrom(final Class<Map<String, List<String>>> c, final Type t,
+ final Annotation[] as, final MediaType mt, final MultivaluedMap<String,
+ String> headers, final InputStream in) throws IOException {
+ try {
+ final JSONObject o = new JSONObject(ReaderWriter.readFromAsString(in, mt));
+
+ final Map<String, List<String>> m = new LinkedHashMap<>();
+ final Iterator keys = o.keys();
+ while (keys.hasNext()) {
+ final String key = (String) keys.next();
+ final List<String> l = new ArrayList<>();
+ m.put(key, l);
+ final JSONArray a = o.getJSONArray(key);
+ for (int i = 0; i < a.length(); i++) {
+ l.add(a.getString(i));
+ }
+ }
+ return m;
+ } catch (final JSONException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mt) {
+ return Map.class.isAssignableFrom(c) && mapListStringType.equals(t);
+ }
+
+ @Override
+ public long getSize(final Map<String, List<String>> t, final Class<?> type, final Type genericType,
+ final Annotation[] as, final MediaType mt) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Map<String, List<String>> t, final Class<?> c, final Type genericType, final Annotation[] as,
+ final MediaType mt, final MultivaluedMap<String, Object> hs,
+ final OutputStream out) throws IOException, WebApplicationException {
+ try {
+ final JSONObject o = new JSONObject();
+ for (final Map.Entry<String, List<String>> e : t.entrySet()) {
+ o.put(e.getKey(), e.getValue());
+ }
+ out.write(o.toString().getBytes());
+ } catch (final JSONException ex) {
+ throw new IOException(ex);
+ }
+ }
+ }
+
+ public static class GenericMapListResource<K, V> {
+
+ @POST
+ public Map<K, List<V>> post(final Map<K, List<V>> m) {
+ return m;
+ }
+ }
+
+ @Path("/MapListResource")
+ public static class MapListResource extends GenericMapListResource<String, String> {
+
+ }
+
+ @Test
+ public void testGenericMapList() throws Exception {
+ final String json = "{\"a\":[\"1\",\"2\"],\"b\":[\"1\",\"2\"]}";
+ assertThat(target("/MapListResource").request().post(Entity.text(json), String.class), is(json));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InjectedProviderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InjectedProviderTest.java
new file mode 100644
index 0000000..5562ed8
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InjectedProviderTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.client.ClientConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ */
+public class InjectedProviderTest extends AbstractTypeTester {
+
+ public static class Bean implements Serializable {
+
+ private String string;
+
+ public Bean() {
+ }
+
+ public Bean(String string) {
+ this.string = string;
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+ }
+
+ @Provider
+ public static class BeanReader implements MessageBodyReader<Bean> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == Bean.class;
+ }
+
+ @Override
+ public Bean readFrom(
+ Class<Bean> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ ObjectInputStream oin = new ObjectInputStream(entityStream);
+ try {
+ return (Bean) oin.readObject();
+ } catch (ClassNotFoundException cause) {
+ throw new IOException(cause);
+ }
+ }
+ }
+
+ @Provider
+ public static class InjectedBeanReaderWriter extends BeanReader implements MessageBodyWriter<Bean> {
+
+ @Context
+ UriInfo uriInfo;
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == Bean.class;
+ }
+
+ @Override
+ public void writeTo(
+ Bean t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ t.setString(uriInfo.getRequestUri().toString());
+ ObjectOutputStream out = new ObjectOutputStream(entityStream);
+ out.writeObject(t);
+ out.flush();
+ }
+
+ @Override
+ public long getSize(Bean t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+ }
+
+ @Path("/one/two/{id}")
+ public static class BeanResource {
+
+ @GET
+ public Bean get() {
+ return new Bean("");
+ }
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(BeanReader.class);
+ }
+
+ @Test
+ public void testBean() throws Exception {
+ Bean bean3 = target("one/two/three").request().get(Bean.class);
+ Bean bean4 = target("one/two/four").request().get(Bean.class);
+
+ final Map<String, String> map3 = new HashMap<String, String>() {{
+ put("id", "three");
+ }};
+ final Map<String, String> map4 = new HashMap<String, String>() {{
+ put("id", "four");
+ }};
+
+ String requestUri3 = target().getUriBuilder()
+ .path(BeanResource.class).buildFromMap(map3).toString();
+ String requestUri4 = target().getUriBuilder()
+ .path(BeanResource.class).buildFromMap(map4).toString();
+
+ assertEquals(requestUri3, bean3.getString());
+ assertEquals(requestUri4, bean4.getString());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InterceptedStreamCloseTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InterceptedStreamCloseTest.java
new file mode 100644
index 0000000..62ac577
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InterceptedStreamCloseTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer for JERSEY-1845.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class InterceptedStreamCloseTest extends JerseyTest {
+ @Path("resource")
+ public static class TestResource {
+ @POST
+ public String post(String entity) {
+ return entity;
+ }
+ }
+
+ public static class ClientInterceptor implements ReaderInterceptor, WriterInterceptor {
+ private volatile int readFromCount = 0;
+ private volatile int inCloseCount = 0;
+ private volatile int writeToCount = 0;
+ private volatile int outCloseCount = 0;
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ readFromCount++;
+
+ context.setInputStream(new FilterInputStream(context.getInputStream()) {
+ @Override
+ public void close() throws IOException {
+ inCloseCount++;
+ super.close();
+ }
+ });
+ return context.proceed();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ writeToCount++;
+
+ context.setOutputStream(new FilterOutputStream(context.getOutputStream()) {
+ @Override
+ public void close() throws IOException {
+ outCloseCount++;
+ super.close();
+ }
+ });
+
+ context.proceed();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Test
+ public void testWrappedStreamClosed() {
+ ClientInterceptor interceptor = new ClientInterceptor();
+
+ final Response response = target().register(interceptor)
+ .path("resource").request().post(Entity.entity("entity", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals("entity", response.readEntity(String.class));
+
+ assertEquals(1, interceptor.readFromCount);
+ assertEquals(1, interceptor.inCloseCount);
+ assertEquals(1, interceptor.writeToCount);
+ assertEquals(1, interceptor.outCloseCount);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidEntityTest.java
new file mode 100644
index 0000000..5da7cc5
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidEntityTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.ResponseProcessingException;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Martin Matula
+ */
+public class InvalidEntityTest extends AbstractTypeTester {
+ @Path("/")
+ public static class TestResource {
+ @GET
+ @Produces("foo/bar")
+ public String getFooBar() {
+ return "foo/bar";
+ }
+ }
+
+ @Test
+ public void testInvalidEntity() {
+ Throwable exception = null;
+ try {
+ target().request("foo/bar").get(Integer.class);
+ } catch (Exception e) {
+ exception = e;
+ }
+ if (!(exception instanceof ResponseProcessingException)) {
+ if (exception != null) {
+ exception.printStackTrace();
+ }
+ fail();
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidFormTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidFormTest.java
new file mode 100644
index 0000000..6af9b30
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/InvalidFormTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ */
+public class InvalidFormTest extends AbstractTypeTester {
+
+ public abstract static class Resource<T> {
+
+ @POST
+ public void post(T t) {
+ }
+ }
+
+ @Path("multivaluedmap")
+ public static class FormMultivaluedMapResource extends Resource<MultivaluedMap<String, String>> {}
+
+ @Test
+ public void testFormMultivaluedMapRepresentation() {
+ _test("multivaluedmap");
+ }
+
+ @Path("form")
+ public static class FormResource extends Resource<Form> {}
+
+ @Test
+ public void testRepresentation() {
+ _test("form");
+ }
+
+ public void _test(String path) {
+ String form = "m=%";
+ Response cr = target(path).request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ assertEquals(400, cr.getStatus());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JAXBContextResolverTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JAXBContextResolverTest.java
new file mode 100644
index 0000000..2f28775
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JAXBContextResolverTest.java
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+@RunWith(Enclosed.class)
+public class JAXBContextResolverTest {
+
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JAXBContextResolver implements ContextResolver<JAXBContext> {
+
+ private JAXBContext context;
+ private int invoked;
+
+ public JAXBContextResolver() {
+ try {
+ this.context = JAXBContext.newInstance(JaxbBean.class);
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public JAXBContext getContext(Class<?> c) {
+ if (JaxbBean.class == c) {
+ invoked++;
+ return context;
+ } else {
+ return null;
+ }
+ }
+
+ public int invoked() {
+ return invoked;
+ }
+ }
+
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class MarshallerResolver implements ContextResolver<Marshaller> {
+
+ private JAXBContext context;
+ private int invoked;
+
+ public MarshallerResolver() {
+ try {
+ this.context = JAXBContext.newInstance(JaxbBean.class);
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public Marshaller getContext(Class<?> c) {
+ if (JaxbBean.class == c) {
+ invoked++;
+ try {
+ return context.createMarshaller();
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public int invoked() {
+ return invoked;
+ }
+ }
+
+ @Provider
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class UnmarshallerResolver implements ContextResolver<Unmarshaller> {
+
+ private JAXBContext context;
+ private int invoked;
+
+ public UnmarshallerResolver() {
+ try {
+ this.context = JAXBContext.newInstance(JaxbBean.class);
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public Unmarshaller getContext(Class<?> c) {
+ if (JaxbBean.class == c) {
+ invoked++;
+ try {
+ return context.createUnmarshaller();
+ } catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public int invoked() {
+ return invoked;
+ }
+ }
+
+ @Path("/")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResource {
+
+ @POST
+ public JaxbBean get(JaxbBean b) {
+ return b;
+ }
+ }
+
+ public static class JAXBContextTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ return new ResourceConfig(JaxbBeanResource.class).registerInstances(cr);
+ }
+
+ @Test
+ public void testJAXBContext() throws Exception {
+ final Response response = target().request(MediaType.APPLICATION_XML_TYPE).post(Entity.xml(new JaxbBean("foo")));
+ assertThat(response.getMediaType(), equalTo(MediaType.APPLICATION_XML_TYPE));
+
+ final JaxbBean foo = response.readEntity(JaxbBean.class);
+ assertThat(foo.value, equalTo("foo"));
+ assertThat(cr.invoked(), equalTo(2));
+ }
+ }
+
+ public static class UnmarshallerTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private MarshallerResolver mr;
+ private UnmarshallerResolver umr;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ mr = new MarshallerResolver();
+ umr = new UnmarshallerResolver();
+ return new ResourceConfig(JaxbBeanResource.class).registerInstances(cr, mr, umr);
+ }
+
+ @Test
+ public void testUnmarshaller() throws Exception {
+ final Response response = target().request(MediaType.APPLICATION_XML_TYPE).post(Entity.xml(new JaxbBean("foo")));
+ assertThat(response.getMediaType(), equalTo(MediaType.APPLICATION_XML_TYPE));
+
+ final JaxbBean foo = response.readEntity(JaxbBean.class);
+ assertThat(foo.value, equalTo("foo"));
+ assertThat(cr.invoked(), equalTo(0));
+ assertThat(mr.invoked(), equalTo(1));
+ assertThat(umr.invoked(), equalTo(1));
+ }
+ }
+
+ @Provider
+ @Produces("application/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JAXBContextResolverApp extends JAXBContextResolver {
+ }
+
+ @Provider
+ @Produces("application/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class MarshallerResolverApp extends MarshallerResolver {
+ }
+
+ @Provider
+ @Produces("application/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class UnmarshallerResolverApp extends UnmarshallerResolver {
+ }
+
+ @Path("/")
+ @Consumes("application/xml")
+ @Produces("application/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResourceApp extends JaxbBeanResource {
+ }
+
+ public static class JAXBContextAppTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private JAXBContextResolverApp crApp;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ crApp = new JAXBContextResolverApp();
+ return new ResourceConfig(JaxbBeanResourceApp.class).registerInstances(cr, crApp);
+ }
+
+ @Test
+ public void testJAXBContextApp() throws Exception {
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(2, crApp.invoked());
+ }
+ }
+
+ public static class UnmarshallerAppTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private MarshallerResolver mr;
+ private UnmarshallerResolver umr;
+ private MarshallerResolverApp mrApp;
+ private UnmarshallerResolverApp umrApp;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ mr = new MarshallerResolver();
+ umr = new UnmarshallerResolver();
+ mrApp = new MarshallerResolverApp();
+ umrApp = new UnmarshallerResolverApp();
+ return new ResourceConfig(JaxbBeanResourceApp.class).registerInstances(cr, mr, umr, mrApp, umrApp);
+ }
+
+ @Test
+ public void testUnmarshallerApp() throws Exception {
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, mr.invoked());
+ assertEquals(0, umr.invoked());
+ assertEquals(1, mrApp.invoked());
+ assertEquals(1, umrApp.invoked());
+
+ assertEquals("foo", target().request()
+ .post(Entity.entity(new JaxbBean("foo"), "application/xml;charset=UTF-8"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, mr.invoked());
+ assertEquals(0, umr.invoked());
+ assertEquals(2, mrApp.invoked());
+ assertEquals(2, umrApp.invoked());
+ }
+ }
+
+ @Provider
+ @Produces("text/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JAXBContextResolverText extends JAXBContextResolver {
+ }
+
+ @Provider
+ @Produces("text/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class MarshallerResolverText extends MarshallerResolver {
+ }
+
+ @Provider
+ @Produces("text/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class UnmarshallerResolverText extends UnmarshallerResolver {
+ }
+
+ @Path("/")
+ @Consumes("text/xml")
+ @Produces("text/xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResourceText extends JaxbBeanResource {
+ }
+
+ public static class JAXBContextTextTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private JAXBContextResolverText crText;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ crText = new JAXBContextResolverText();
+ return new ResourceConfig(JaxbBeanResourceText.class).registerInstances(cr, crText);
+ }
+
+ @Test
+ public void testJAXBContextText() throws Exception {
+ assertEquals("foo", target().request().post(Entity.entity(new JaxbBean("foo"), "text/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(2, crText.invoked());
+ }
+ }
+
+ public static class UnmarshallerTextTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private MarshallerResolver mr;
+ private UnmarshallerResolver umr;
+ private MarshallerResolverText mrText;
+ private UnmarshallerResolverText umrText;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ mr = new MarshallerResolver();
+ umr = new UnmarshallerResolver();
+ mrText = new MarshallerResolverText();
+ umrText = new UnmarshallerResolverText();
+ return new ResourceConfig(JaxbBeanResourceText.class).registerInstances(cr, mr, umr, mrText, umrText);
+ }
+
+ @Test
+ public void testUnmarshallerText() throws Exception {
+ assertEquals("foo", target().request().post(Entity.entity(new JaxbBean("foo"), "text/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, mr.invoked());
+ assertEquals(0, umr.invoked());
+ assertEquals(1, mrText.invoked());
+ assertEquals(1, umrText.invoked());
+ }
+ }
+
+ @Provider
+ @Produces("text/foo+xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class MarshallerResolverFoo extends MarshallerResolver {
+ }
+
+ @Provider
+ @Produces("text/foo+xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class UnmarshallerResolverFoo extends UnmarshallerResolver {
+ }
+
+ @Path("/")
+ @Consumes("text/foo+xml")
+ @Produces("text/foo+xml")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResourceFoo extends JaxbBeanResource {
+ }
+
+ public static class UnmarshallerFooTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private MarshallerResolver mr;
+ private UnmarshallerResolver umr;
+ private MarshallerResolverFoo mrFoo;
+ private UnmarshallerResolverFoo umrFoo;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ mr = new MarshallerResolver();
+ umr = new UnmarshallerResolver();
+ mrFoo = new MarshallerResolverFoo();
+ umrFoo = new UnmarshallerResolverFoo();
+ return new ResourceConfig(JaxbBeanResourceFoo.class).registerInstances(cr, mr, umr, mrFoo, umrFoo);
+ }
+
+ @Test
+ public void testUnmarshallerFoo() throws Exception {
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "text/foo+xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, mr.invoked());
+ assertEquals(0, umr.invoked());
+ assertEquals(1, mrFoo.invoked());
+ assertEquals(1, umrFoo.invoked());
+
+ assertEquals("foo", target().request()
+ .post(Entity.entity(new JaxbBean("foo"), "text/foo+xml;charset=UTF-8"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, mr.invoked());
+ assertEquals(0, umr.invoked());
+ assertEquals(2, mrFoo.invoked());
+ assertEquals(2, umrFoo.invoked());
+ }
+ }
+
+ @Path("/")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResourceAll {
+
+ @POST
+ @Consumes("application/foo+xml")
+ @Produces("application/foo+xml")
+ public JaxbBean get(JaxbBean b) {
+ return b;
+ }
+
+ @POST
+ @Consumes("application/xml")
+ @Produces("application/xml")
+ public JaxbBean getApp(JaxbBean b) {
+ return b;
+ }
+
+ @POST
+ @Consumes("text/xml")
+ @Produces("text/xml")
+ public JaxbBean getText(JaxbBean b) {
+ return b;
+ }
+ }
+
+ public static class JAXBContextAllTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private JAXBContextResolverApp crApp;
+ private JAXBContextResolverText crText;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ crApp = new JAXBContextResolverApp();
+ crText = new JAXBContextResolverText();
+ return new ResourceConfig(JaxbBeanResourceAll.class).registerInstances(cr, crApp, crText);
+ }
+
+ @Test
+ public void testJAXBContextAll() throws Exception {
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/foo+xml"), JaxbBean.class).value);
+ assertEquals(2, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/xml"), JaxbBean.class).value);
+ assertEquals(2, cr.invoked());
+ assertEquals(2, crApp.invoked());
+ assertEquals(0, crText.invoked());
+
+ assertEquals("foo", target().request().post(Entity.entity(new JaxbBean("foo"), "text/xml"), JaxbBean.class).value);
+ assertEquals(2, cr.invoked());
+ assertEquals(2, crApp.invoked());
+ assertEquals(2, crText.invoked());
+ }
+ }
+
+ public static class UnmarshallerAllTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private JAXBContextResolverApp crApp;
+ private JAXBContextResolverText crText;
+ private MarshallerResolver mr;
+ private UnmarshallerResolver umr;
+ private MarshallerResolverApp mrApp;
+ private UnmarshallerResolverApp umrApp;
+ private MarshallerResolverText mrText;
+ private UnmarshallerResolverText umrText;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ crApp = new JAXBContextResolverApp();
+ crText = new JAXBContextResolverText();
+ mr = new MarshallerResolver();
+ umr = new UnmarshallerResolver();
+ mrApp = new MarshallerResolverApp();
+ umrApp = new UnmarshallerResolverApp();
+ mrText = new MarshallerResolverText();
+ umrText = new UnmarshallerResolverText();
+ return new ResourceConfig(JaxbBeanResourceAll.class).registerInstances(cr, crApp, crText, mr, umr,
+ mrApp, umrApp, mrText, umrText);
+ }
+
+ @Test
+ public void testUnmarshallerAll() throws Exception {
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/foo+xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+ assertEquals(1, mr.invoked());
+ assertEquals(1, umr.invoked());
+ assertEquals(0, mrApp.invoked());
+ assertEquals(0, umrApp.invoked());
+ assertEquals(0, mrText.invoked());
+ assertEquals(0, umrText.invoked());
+
+ assertEquals("foo",
+ target().request().post(Entity.entity(new JaxbBean("foo"), "application/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+ assertEquals(1, mr.invoked());
+ assertEquals(1, umr.invoked());
+ assertEquals(1, mrApp.invoked());
+ assertEquals(1, umrApp.invoked());
+ assertEquals(0, mrText.invoked());
+ assertEquals(0, umrText.invoked());
+
+ assertEquals("foo", target().request().post(Entity.entity(new JaxbBean("foo"), "text/xml"), JaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+ assertEquals(1, mr.invoked());
+ assertEquals(1, umr.invoked());
+ assertEquals(1, mrApp.invoked());
+ assertEquals(1, umrApp.invoked());
+ assertEquals(1, mrText.invoked());
+ assertEquals(1, umrText.invoked());
+ }
+ }
+
+ @XmlRootElement
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class OtherJaxbBean {
+
+ public String value;
+
+ public OtherJaxbBean() {
+ }
+
+ public OtherJaxbBean(String str) {
+ value = str;
+ }
+
+ public boolean equals(Object o) {
+ return o instanceof JaxbBean && ((JaxbBean) o).value.equals(value);
+ }
+
+ public String toString() {
+ return "JAXBClass: " + value;
+ }
+ }
+
+ @Path("/")
+ @Ignore("This class is not a test class & must be ignored by the Enclosed test runner.")
+ public static class JaxbBeanResourceAllOtherJaxbBean {
+
+ @POST
+ @Consumes("application/foo+xml")
+ @Produces("application/foo+xml")
+ public OtherJaxbBean get(OtherJaxbBean b) {
+ return b;
+ }
+
+ @POST
+ @Consumes("application/xml")
+ @Produces("application/xml")
+ public OtherJaxbBean getApp(OtherJaxbBean b) {
+ return b;
+ }
+
+ @POST
+ @Consumes("text/xml")
+ @Produces("text/xml")
+ public OtherJaxbBean getText(OtherJaxbBean b) {
+ return b;
+ }
+ }
+
+ public static class JAXBContextAllWithOtherJaxbBeanTest extends AbstractTypeTester {
+
+ private JAXBContextResolver cr;
+ private JAXBContextResolverApp crApp;
+ private JAXBContextResolverText crText;
+
+ @Override
+ protected Application configure() {
+ cr = new JAXBContextResolver();
+ crApp = new JAXBContextResolverApp();
+ crText = new JAXBContextResolverText();
+ return new ResourceConfig(JaxbBeanResourceAllOtherJaxbBean.class).registerInstances(cr, crApp, crText);
+ }
+
+ @Test
+ public void testJAXBContextAllWithOtherJaxbBean() throws Exception {
+ assertEquals("foo", target().request()
+ .post(Entity.entity(new OtherJaxbBean("foo"), "application/foo+xml"), OtherJaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+
+ assertEquals("foo", target().request()
+ .post(Entity.entity(new OtherJaxbBean("foo"), "application/xml"), OtherJaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+
+ assertEquals("foo",
+ target().request().post(Entity.entity(new OtherJaxbBean("foo"), "text/xml"), OtherJaxbBean.class).value);
+ assertEquals(0, cr.invoked());
+ assertEquals(0, crApp.invoked());
+ assertEquals(0, crText.invoked());
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBean.java
new file mode 100644
index 0000000..6acd2df
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBean.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Doug Kohlert
+ */
+@XmlRootElement(name = "jaxbBean")
+public class JaxbBean {
+
+ public String value;
+
+ public JaxbBean() {
+ }
+
+ public JaxbBean(String str) {
+ value = str;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof JaxbBean)) {
+ return false;
+ }
+ return ((JaxbBean) o).value.equals(value);
+ }
+
+ public String toString() {
+ return "JAXBClass: " + value;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBeanType.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBeanType.java
new file mode 100644
index 0000000..deab480
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JaxbBeanType.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ * @author Paul Sandoz
+ */
+@XmlType(name = "dada")
+public class JaxbBeanType {
+
+ public String value;
+
+ public JaxbBeanType() {
+ }
+
+ public JaxbBeanType(String str) {
+ value = str;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof JaxbBeanType)) {
+ return false;
+ }
+ return ((JaxbBeanType) o).value.equals(value);
+ }
+
+ public String toString() {
+ return "JaxbBeanType: " + value;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JsonMoxyTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JsonMoxyTest.java
new file mode 100644
index 0000000..35a03a1
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/JsonMoxyTest.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@RunWith(ConcurrentRunner.class)
+public class JsonMoxyTest extends AbstractTypeTester {
+
+ @Path("JAXBElementListResource")
+ @Produces({"application/json"})
+ @Consumes({"application/json"})
+ public static class JAXBElementListResource extends AResource<List<JAXBElement<String>>> {
+ }
+
+ private List<JAXBElement<String>> getJAXBElementList() {
+ return Arrays.asList(getJAXBElementArray());
+ }
+
+ public static final class MoxyJsonConfigurationContextResolver implements ContextResolver<MoxyJsonConfig> {
+
+ @Override
+ public MoxyJsonConfig getContext(final Class<?> type) {
+ final MoxyJsonConfig configuration = new MoxyJsonConfig();
+ configuration.setIncludeRoot(true);
+ return configuration;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void _testListOrArray(final boolean isList, final MediaType mt) {
+ final Object in = isList ? getJAXBElementList() : getJAXBElementArray();
+ final GenericType gt = isList ? new GenericType<List<JAXBElement<String>>>() {
+ } : new GenericType<JAXBElement<String>[]>() {
+ };
+
+ final WebTarget target = target(isList ? "JAXBElementListResource" : "JAXBElementArrayResource");
+ final Object out = target.request(mt).post(Entity.entity(new GenericEntity(in, gt.getType()), mt), gt);
+
+ final List<JAXBElement<String>> inList =
+ isList ? ((List<JAXBElement<String>>) in) : Arrays.asList((JAXBElement<String>[]) in);
+ final List<JAXBElement<String>> outList = isList ? ((List<JAXBElement<String>>) out) : Arrays
+ .asList((JAXBElement<String>[]) out);
+ assertEquals("Lengths differ", inList.size(), outList.size());
+ for (int i = 0; i < inList.size(); i++) {
+ assertEquals("Names of elements at index " + i + " differ", inList.get(i).getName(), outList.get(i).getName());
+ assertEquals("Values of elements at index " + i + " differ", inList.get(i).getValue(), outList.get(i).getValue());
+ }
+ }
+
+ @Test
+ public void testJAXBElementListJSONRepresentation() {
+ _testListOrArray(true, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Path("JAXBElementArrayResource")
+ @Produces({"application/json"})
+ @Consumes({"application/json"})
+ public static class JAXBElementArrayResource extends AResource<JAXBElement<String>[]> {
+ }
+
+ @SuppressWarnings("unchecked")
+ private JAXBElement<String>[] getJAXBElementArray() {
+ return new JAXBElement[] {
+ new JAXBElement(QName.valueOf("element1"), String.class, "ahoj"),
+ new JAXBElement(QName.valueOf("element2"), String.class, "nazdar")
+ };
+ }
+
+ @Test
+ public void testJAXBElementArrayJSONRepresentation() {
+ _testListOrArray(false, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return ((ResourceConfig) super.configure())
+ .register(MoxyJsonFeature.class)
+ .register(MoxyJsonConfigurationContextResolver.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+ config.register(MoxyJsonFeature.class);
+ config.register(MoxyJsonConfigurationContextResolver.class);
+ }
+
+ @Path("JAXBElementBeanJSONResource")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class JAXBElementBeanJSONResource extends AResource<JAXBElement<String>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanJSONRepresentation() {
+ final WebTarget target = target("JAXBElementBeanJSONResource");
+
+ final GenericType<JAXBElement<String>> genericType = new GenericType<JAXBElement<String>>() {
+ };
+ final GenericEntity<JAXBElement<String>> jaxbElementGenericEntity = new GenericEntity<>(
+ new JAXBElement<>(new QName("test"), String.class, "CONTENT"), genericType.getType());
+
+ final Response rib = target.request().post(
+ Entity.entity(jaxbElementGenericEntity, "application/json"));
+
+ // TODO: the following would not be needed if i knew how to workaround JAXBElement<String>.class literal
+ final byte[] inBytes = getRequestEntity();
+ final byte[] outBytes = getEntityAsByteArray(rib);
+
+ assertEquals(new String(outBytes), inBytes.length, outBytes.length);
+ for (int i = 0; i < inBytes.length; i++) {
+ if (inBytes[i] != outBytes[i]) {
+ assertEquals("Index: " + i, inBytes[i], outBytes[i]);
+ }
+ }
+ }
+
+ @Path("JaxbBeanResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JaxbBeanResourceJSON extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationJSON() {
+ final WebTarget target = target("JaxbBeanResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JaxbBeanResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JaxbBeanResourceJSONMediaType extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationJSONMediaType() {
+ final WebTarget target = target("JaxbBeanResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBElementBeanResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBElementBeanResourceJSON extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationJSON() {
+ final WebTarget target = target("JAXBElementBeanResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBElementBeanResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBElementBeanResourceJSONMediaType extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationJSONMediaType() {
+ final WebTarget target = target("JAXBElementBeanResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBean.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBTypeResourceJSON {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationJSON() {
+ final WebTarget target = target("JAXBTypeResourceJSON");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/json"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBTypeResourceJSONMediaType {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationJSONMediaType() {
+ final WebTarget target = target("JAXBTypeResourceJSONMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/foo+json"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBListResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBListResource {
+
+ @POST
+ public List<JaxbBean> post(final List<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("set")
+ public Set<JaxbBean> postSet(final Set<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("queue")
+ public Queue<JaxbBean> postQueue(final Queue<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("stack")
+ public Stack<JaxbBean> postStack(final Stack<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("custom")
+ public MyArrayList<JaxbBean> postCustom(final MyArrayList<JaxbBean> l) {
+ return l;
+ }
+
+ @GET
+ public Collection<JaxbBean> get() {
+ final ArrayList<JaxbBean> l = new ArrayList<>();
+ l.add(new JaxbBean("one"));
+ l.add(new JaxbBean("two"));
+ l.add(new JaxbBean("three"));
+ return l;
+ }
+
+ @POST
+ @Path("type")
+ public List<JaxbBean> postType(final Collection<JaxbBeanType> l) {
+ final List<JaxbBean> beans = new ArrayList<>();
+ for (final JaxbBeanType t : l) {
+ beans.add(new JaxbBean(t.value));
+ }
+ return beans;
+ }
+ }
+
+ @Path("JAXBListResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBListResourceMediaType extends JAXBListResource {
+ }
+
+ @Path("JAXBListResourceJSON")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class JAXBListResourceJSON extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONCollection() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ final Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/json"), new GenericType<Collection<JaxbBean>>() {
+ });
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/json"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONLinkedList() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ final Collection<JaxbBean> b;
+
+ a = new LinkedList<>(a);
+ b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
+ }, "application/json"), new GenericType<Queue<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONSet() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ final Collection<JaxbBean> b;
+
+ a = new HashSet<>(a);
+ b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
+ }, "application/json"), new GenericType<Set<JaxbBean>>() {
+ });
+ final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
+ @Override
+ public int compare(final JaxbBean t, final JaxbBean t1) {
+ return t.value.compareTo(t1.value);
+ }
+ };
+ final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
+ final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
+ t1.addAll(a);
+ t2.addAll(b);
+ assertEquals(t1, t2);
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONStack() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ final Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ final Collection<JaxbBean> b;
+
+ final Stack<JaxbBean> s = new Stack<>();
+ s.addAll(a);
+ b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
+ }, "application/json"), new GenericType<Stack<JaxbBean>>() {
+ });
+ assertEquals(s, b);
+ }
+
+ @Test
+ @Ignore("Until JERSEY-2825 is fixed.")
+ public void testJAXBListRepresentationJSONArrayList() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSON");
+
+ Collection<JaxbBean> a = target.request().get(new GenericType<Collection<JaxbBean>>() {});
+ final Collection<JaxbBean> b;
+
+ a = new MyArrayList<>(a);
+ b = target.path("custom").request()
+ .post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {}, "application/json"),
+ new GenericType<MyArrayList<JaxbBean>>() {});
+ assertEquals(a, b);
+ }
+
+ @Path("JAXBListResourceJSONMediaType")
+ @Produces("application/foo+json")
+ @Consumes("application/foo+json")
+ public static class JAXBListResourceJSONMediaType extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationJSONMediaType() throws Exception {
+ final WebTarget target = target("JAXBListResourceJSONMediaType");
+
+ final Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+json"), new GenericType<Collection<JaxbBean>>() {
+ });
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+json"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MediaTypeSelectionTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MediaTypeSelectionTest.java
new file mode 100644
index 0000000..77f7df7
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MediaTypeSelectionTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class MediaTypeSelectionTest extends AbstractTypeTester {
+ @Path("form")
+ public static class FormResource {
+ @POST
+ public Response post(MultivaluedMap<String, String> data) {
+ return Response.ok(data, MediaType.APPLICATION_FORM_URLENCODED_TYPE).build();
+ }
+ }
+
+ @Path("foo")
+ public static class FooResource {
+ @POST
+ @Consumes("foo/*")
+ @Produces("foo/*")
+ public String foo(String foo) {
+ return foo;
+ }
+ }
+
+ @Path("text")
+ public static class TextResource {
+ @GET
+ @Produces("text/*")
+ public String getText() {
+ return "text";
+ }
+
+ @GET
+ @Produces("application/*")
+ @Path("any")
+ public String getAny() {
+ return "text";
+ }
+
+ @POST
+ @Produces("text/*")
+ public Response post(String entity) {
+ return Response.ok().entity("entity").build();
+ }
+ }
+
+ @Path("wildcard")
+ public static class WildCardResource {
+ @POST
+ public String wildCard(String wc) {
+ return wc;
+ }
+ }
+
+ @Path("jira/1518")
+ public static class Issue1518Resource {
+ @POST
+ @Consumes("text/plain;qs=0.7")
+ public String never() {
+ throw new WebApplicationException(Response.Status.CONFLICT);
+ }
+
+ @POST
+ @Consumes("text/*")
+ public String text() {
+ return "1518";
+ }
+ }
+
+ // JERSEY-1518 reproducer test
+ @Test
+ public void testQsInConsumes() {
+ Response r = target("jira/1518").request(MediaType.TEXT_PLAIN_TYPE).post(Entity.text("request"));
+ assertEquals(200, r.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, r.getMediaType());
+ assertEquals("1518", r.readEntity(String.class));
+ }
+
+ // JERSEY-1187 regression test
+ @Test
+ public void testExplicitMediaType() {
+ Response r = target("form").request().post(Entity.form(new Form().param("a", "b")));
+ assertEquals(MediaType.APPLICATION_FORM_URLENCODED_TYPE, r.getMediaType());
+ assertEquals("b", r.readEntity(Form.class).asMap().getFirst("a"));
+ }
+
+ @Test
+ public void testAmbiguousWildcard() {
+ Response r = target("foo").request().post(Entity.entity("test", "foo/plain"));
+ assertEquals(406, r.getStatus());
+ }
+
+ @Test
+ public void testWildcardInSubType() {
+ Response r = target("text").request("text/*").get();
+ assertEquals(406, r.getStatus());
+ }
+
+ @Test
+ public void testWildcardInSubTypePost() {
+ Response r = target("text").request("text/*").post(Entity.entity("test", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(406, r.getStatus());
+ }
+
+ @Test
+ public void testWildcardInSubType2() {
+ Response r = target("text").request("*/*").get();
+ assertEquals(406, r.getStatus());
+ }
+
+ @Test
+ public void testWildcardsInTypeAndSubType() {
+ Response r = target("text/any").request("*/*").get();
+ assertEquals(200, r.getStatus());
+ assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, r.getMediaType());
+ }
+
+ @Test
+ public void testNoAcceptHeader() {
+ // This test is testing the situation when the client sends no Accept header to the server and it expects
+ // APPLICATION_OCTET_STREAM_TYPE to be returned. But when no Accept header is defined by the client api the
+ // HttpURLConnection (in HttpUrlConnector) always put there some default Accept header (like */*, text/plain, ...).
+ // To overwrite this behaviour we set Accept to empty String. This works fine as the server code handles empty
+ // Accept header like no Accept header.
+ final MultivaluedHashMap headers = new MultivaluedHashMap();
+ headers.add("Accept", "");
+
+ Response r = target("text/any").request().headers(headers).get();
+ assertEquals(200, r.getStatus());
+ assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, r.getMediaType());
+ }
+
+ @Test
+ public void testSpecific() {
+ Response r = target("foo").request("foo/plain").post(Entity.entity("test", "foo/plain"));
+ assertEquals(MediaType.valueOf("foo/plain"), r.getMediaType());
+ assertEquals("test", r.readEntity(String.class));
+ }
+
+ @Test
+ @Ignore("JSONB breaks this test.")
+ public void testApplicationWildCard() {
+ Response r = target("wildcard").request("application/*").post(Entity.text("test"));
+ assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, r.getMediaType());
+ assertEquals("test", r.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MessageBodyProviderAnnotationsTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MessageBodyProviderAnnotationsTest.java
new file mode 100644
index 0000000..897bfe4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MessageBodyProviderAnnotationsTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests annotations passed to message body provider.
+ *
+ * @author Miroslav Fuksa
+ */
+public class MessageBodyProviderAnnotationsTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ContainerReaderWriter.class, Resource.class);
+ }
+
+ @Test
+ public void testWriter() {
+ String get = target().path("test").request("test/text").get(String.class);
+ assertEquals("get-ok", get);
+ }
+
+ @Test
+ public void testReader() {
+ String get = target().path("test").request("text/plain").post(Entity.entity("test", "test/text"), String.class);
+ assertEquals("ok", get);
+ }
+
+
+ @Produces("test/text")
+ @Consumes("test/text")
+ public static class ContainerReaderWriter implements MessageBodyWriter<String>, MessageBodyReader<Bean> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ OutputStreamWriter osw = new OutputStreamWriter(entityStream);
+
+ if (compareAnnotations(new Class<?>[]{MyAnnotation.class, Produces.class, GET.class}, annotations)) {
+ osw.write(s + "-ok");
+ } else {
+ osw.write(s + "-fail");
+ }
+ osw.flush();
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == Bean.class;
+ }
+
+ @Override
+ public Bean readFrom(Class<Bean> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
+ WebApplicationException {
+ if (compareAnnotations(new Class<?>[]{MyAnnotation.class}, annotations)) {
+ return new Bean("ok");
+ } else {
+ return new Bean("fail");
+ }
+ }
+ }
+
+ public static class Bean {
+ private final String value;
+
+ public Bean(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ private static boolean compareAnnotations(Class[] expected, Annotation[] actual) {
+ if (expected.length != actual.length) {
+ return false;
+ }
+
+ for (Class<?> e : expected) {
+ boolean found = false;
+ for (Annotation a : actual) {
+ if (e.equals(a.annotationType())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static final Annotation ANNOTATION;
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface MyAnnotation {
+ }
+
+ static {
+ @MyAnnotation
+ class TempClass {
+ }
+ ;
+ ANNOTATION = TempClass.class.getAnnotation(MyAnnotation.class);
+ }
+
+ @Path("test")
+ public static class Resource {
+ @GET
+ @Produces("test/text")
+ public Response get() {
+ Response response = Response.ok().entity("get", new Annotation[]{ANNOTATION}).build();
+ return response;
+ }
+
+ @POST
+ @Consumes("test/text")
+ @Produces("text/plain")
+ public String post(@MyAnnotation Bean entity) {
+ return entity.getValue();
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MultipartTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MultipartTest.java
new file mode 100644
index 0000000..449da72
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MultipartTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Martin Matula
+ */
+public class MultipartTest extends JerseyTest {
+
+ @SuppressWarnings("UnusedDeclaration")
+ public static class MyObject {
+
+ private String value;
+
+ public MyObject() {
+ }
+
+ public MyObject(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ @Path("/")
+ public static class MultipartResource {
+
+ @POST
+ @Path("filename")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String filename(final FormDataMultiPart entity) {
+ return entity.getField("text").getValue() + entity.getField("file").getContentDisposition().getFileName();
+ }
+
+ @POST
+ @Path("mbr")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response mbr(final FormDataMultiPart entity) {
+ entity.getField("text").getValueAs(MultipartResource.class);
+
+ return Response.ok("ko").build();
+ }
+
+ @POST
+ @Path("listAsParameter")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public String process(@FormDataParam(value = "object") final MyObject object,
+ @FormDataParam(value = "list") final List<MyObject> list) {
+ String value = object.value;
+
+ for (final MyObject obj : list) {
+ value += "_" + obj.value;
+ }
+
+ return value;
+ }
+ }
+
+ public static class MessageBodyProvider
+ implements MessageBodyReader<MultipartResource>, MessageBodyWriter<MultipartResource> {
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public MultipartResource readFrom(final Class<MultipartResource> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ throw new IOException("IOE");
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final MultipartResource multipartResource, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final MultipartResource multipartResource, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+ throws IOException, WebApplicationException {
+
+ throw new IOException("IOE");
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MultipartResource.class, MessageBodyProvider.class)
+ .register(MultiPartFeature.class)
+ .register(JacksonFeature.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(MultiPartFeature.class);
+ config.register(JacksonFeature.class);
+ }
+
+ @Test
+ public void testFileNameInternetExplorer() throws Exception {
+ final InputStream entity = getClass().getResourceAsStream("multipart-testcase.txt");
+ final Response response = target("filename")
+ .request()
+ .header("User-Agent", "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)")
+ .post(Entity.entity(entity, "multipart/form-data; boundary=---------------------------7dc941520888"));
+
+ assertThat(response.readEntity(String.class), equalTo("bhhklbpom.xml"));
+ }
+
+ @Test
+ public void testFileName() throws Exception {
+ final InputStream entity = getClass().getResourceAsStream("multipart-testcase.txt");
+ final Response response = target("filename")
+ .request()
+ .post(Entity.entity(entity, "multipart/form-data; boundary=---------------------------7dc941520888"));
+
+ assertThat(response.readEntity(String.class), equalTo("bhhklbC:javaprojectsmultipart-testcasepom.xml"));
+ }
+
+ @Test
+ public void testMbrExceptionServer() throws Exception {
+ final InputStream entity = getClass().getResourceAsStream("multipart-testcase.txt");
+ final Response response = target("mbr")
+ .request()
+ .post(Entity.entity(entity, "multipart/form-data; boundary=---------------------------7dc941520888"));
+
+ assertThat(response.getStatus(), equalTo(500));
+ }
+
+ /**
+ * Test that injection of a list (specific type) works.
+ */
+ @Test
+ public void testSpecificListAsParameter() throws Exception {
+ final MyObject object = new MyObject("object");
+ final List<MyObject> list = Arrays.asList(new MyObject("list1"), new MyObject("list2"));
+
+ final FormDataMultiPart mp = new FormDataMultiPart();
+ mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("object").fileName("object").build(),
+ object, MediaType.APPLICATION_JSON_TYPE));
+ mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("list").fileName("list").build(),
+ list, MediaType.APPLICATION_JSON_TYPE));
+
+ final Response response = target("listAsParameter")
+ .request().post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE));
+
+ assertThat(response.readEntity(String.class), is("object_list1_list2"));
+ }
+
+ @Test
+ public void testEmptyEntity() throws Exception {
+ final Response response = target("filename")
+ .request()
+ .post(Entity.entity(null, MediaType.MULTIPART_FORM_DATA_TYPE));
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+ @Test
+ public void testEmptyEntityWithoutContentType() throws Exception {
+ final Response response = target("filename")
+ .request()
+ .post(null);
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MyArrayList.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MyArrayList.java
new file mode 100644
index 0000000..1919214
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/MyArrayList.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Martin Matula
+ */
+public class MyArrayList<T> extends ArrayList<T> {
+
+ public MyArrayList() {
+
+ }
+
+ public MyArrayList(final Collection<T> a) {
+ super(a);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/NoMessageBodyWorkerTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/NoMessageBodyWorkerTest.java
new file mode 100644
index 0000000..454fac3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/NoMessageBodyWorkerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ */
+public class NoMessageBodyWorkerTest extends AbstractTypeTester {
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = (ResourceConfig) super.configure();
+ resourceConfig.property(CommonProperties.MOXY_JSON_FEATURE_DISABLE, true);
+ return resourceConfig;
+ }
+
+ @Path("nobodyreader")
+ public static class NoMessageBodyReaderResource {
+
+ @POST
+ public void post(NoMessageBodyReaderResource t) {
+ }
+ }
+
+ @Test
+ public void testNoMessageBodyReaderResource() {
+ Response r = target("nobodyreader").request().post(Entity.text("a"));
+ assertEquals(415, r.getStatus());
+ }
+
+ @Path("nobodywriter")
+ public static class NoMessageBodyWriterResource {
+
+ @GET
+ public NoMessageBodyWriterResource get() {
+ return new NoMessageBodyWriterResource();
+ }
+ }
+
+ @Test
+ public void testNoMessageBodyWriterResource() {
+ Response r = target("nobodywriter").request().get();
+ assertEquals(500, r.getStatus());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentOrderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentOrderTest.java
new file mode 100644
index 0000000..ef7bba6
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentOrderTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the correct order of providers.
+ *
+ * @author Paul Sandoz
+ */
+public class ParameterTypeArgumentOrderTest extends AbstractParameterTypeArgumentOrderTest {
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(AWriter.class, BWriter.class, CWriter.class, ClassResource.class);
+ }
+
+ @Test
+ public void testClassResource() {
+ assertEquals("AA", target().path("a").request().get(String.class));
+ assertEquals("BB", target().path("b").request().get(String.class));
+ assertEquals("CC", target().path("c").request().get(String.class));
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentResourceReaderWriterOrderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentResourceReaderWriterOrderTest.java
new file mode 100644
index 0000000..58aa798
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentResourceReaderWriterOrderTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the correct order of providers.
+ *
+ * @author Paul Sandoz
+ */
+public class ParameterTypeArgumentResourceReaderWriterOrderTest extends AbstractParameterTypeArgumentOrderTest {
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(AReaderWriter.class, BReaderWriter.class, CReaderWriter.class, ClassResource.class);
+ }
+
+ @Test
+ public void testClassResource() {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ assertEquals("AA", target().path("a").request("text/html").get(String.class));
+ assertEquals("BB", target().path("b").request("text/html").get(String.class));
+ assertEquals("CC", target().path("c").request("text/html").get(String.class));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentReversedOrderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentReversedOrderTest.java
new file mode 100644
index 0000000..8fc826b
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ParameterTypeArgumentReversedOrderTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the correct order of providers.
+ *
+ * @author Paul Sandoz
+ */
+public class ParameterTypeArgumentReversedOrderTest extends AbstractParameterTypeArgumentOrderTest {
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(CWriter.class, BWriter.class, AWriter.class, ClassResource.class);
+ }
+
+ @Test
+ public void testClassResource() {
+ assertEquals("AA", target().path("a").request().get(String.class));
+ assertEquals("BB", target().path("b").request().get(String.class));
+ assertEquals("CC", target().path("c").request().get(String.class));
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/RenderedImageTypeTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/RenderedImageTypeTest.java
new file mode 100644
index 0000000..1d379e0
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/RenderedImageTypeTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class RenderedImageTypeTest extends JerseyTest {
+
+ @Path("/")
+ public static class ImageResource {
+
+ @Consumes("image/gif")
+ @Produces("image/png")
+ @POST
+ public RenderedImage postGif(final RenderedImage image) {
+ return image;
+ }
+
+ @Consumes("image/png")
+ @Produces("image/png")
+ @POST
+ public RenderedImage postPng(final RenderedImage image) {
+ return image;
+ }
+
+ @Path("sub")
+ @Consumes("application/octet-stream")
+ @Produces("image/png")
+ @POST
+ public RenderedImage postUndefined(final BufferedImage image) {
+ return image;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ImageResource.class);
+ }
+
+ @Test
+ public void testPostPng() throws Exception {
+ final InputStream stream = getClass().getResourceAsStream("Jersey_yellow.png");
+ Response response = target().request().post(Entity.entity(stream, "image/png"));
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+
+ final RenderedImage image = response.readEntity(RenderedImage.class);
+ assertThat(image, notNullValue());
+
+ response = target().request().post(Entity.entity(image, "image/png"));
+ assertThat(response.readEntity(RenderedImage.class), notNullValue());
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+ }
+
+ @Test
+ public void testPostGif() throws Exception {
+ final InputStream stream = getClass().getResourceAsStream("duke_rocket.gif");
+ Response response = target().request().post(Entity.entity(stream, "image/gif"));
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+
+ final RenderedImage image = response.readEntity(RenderedImage.class);
+ assertThat(image, notNullValue());
+
+ response = target().request().post(Entity.entity(image, "image/png"));
+ assertThat(response.readEntity(RenderedImage.class), notNullValue());
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+ }
+
+ @Test
+ public void testPostUndefined() throws Exception {
+ final InputStream stream = getClass().getResourceAsStream("duke_rocket.gif");
+ Response response = target("sub").request().post(Entity.entity(stream, "application/octet-stream"));
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+
+ final RenderedImage image = response.readEntity(RenderedImage.class);
+ assertThat(image, notNullValue());
+
+ response = target().request().post(Entity.entity(image, "image/png"));
+ assertThat(response.readEntity(RenderedImage.class), notNullValue());
+ assertThat(Long.valueOf(response.getHeaderString("Content-Length")), greaterThan(0L));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/StreamingOutputTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/StreamingOutputTest.java
new file mode 100644
index 0000000..9bdf547
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/StreamingOutputTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+@Path("/")
+public class StreamingOutputTest extends JerseyTest {
+ @GET
+ @Path("wae")
+ public StreamingOutput test2() {
+ return new StreamingOutput() {
+ public void write(OutputStream output) throws IOException {
+ throw new WebApplicationException(Response.Status.BAD_GATEWAY.getStatusCode());
+ }
+ };
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(StreamingOutputTest.class);
+ }
+
+ @Test
+ public void testWebApplicationException() {
+ Response r = target("wae").request().get();
+ assertEquals(Response.Status.BAD_GATEWAY.getStatusCode(), r.getStatusInfo().getStatusCode());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/SubResourceDynamicProxyTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/SubResourceDynamicProxyTest.java
new file mode 100644
index 0000000..eab22f4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/SubResourceDynamicProxyTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer for JERSEY-2541.
+ *
+ * Make sure that type parameter will be retained for resource method
+ * of a sub-resource locator that returns a dynamic proxy.
+ * This test should cover also the EJB case, as the common cause
+ * is missing type parameter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class SubResourceDynamicProxyTest extends JerseyTest {
+
+ @Override
+ public Application configure() {
+ return new ResourceConfig(ListProvider.class, RootResource.class);
+ }
+
+ /**
+ * Sub-resource interface so that it is easy to make a dynamic proxy
+ * with the standard Java reflection API.
+ */
+ public static interface SubResource {
+
+ @GET
+ public List<Foo> getGreeting();
+ }
+
+ /**
+ * Helper type to be used as a type parameter.
+ */
+ public static class Foo {
+ }
+
+ /**
+ * Message body writer that uses to check presence of type parameter in the provided entity type.
+ * If no type parameter is found the provider refuses to process corresponding entity,
+ * which would lead to an error.
+ */
+ @Provider
+ public static class ListProvider implements MessageBodyWriter<List<Foo>> {
+
+ /**
+ * This is the data that would be written to the response body by the {@link ListProvider} bellow.
+ */
+ static final String CHECK_DATA = "ensure this one makes it to the client";
+
+ /**
+ * We need to work with a non-null entity here so that the worker could do it's job.
+ */
+ static final LinkedList<Foo> TEST_ENTITY = new LinkedList<Foo>() {
+ {
+ add(new Foo());
+ }
+ };
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ if (!(genericType instanceof ParameterizedType)) {
+ return false;
+ }
+
+ final ParameterizedType pt = (ParameterizedType) genericType;
+
+ if (pt.getActualTypeArguments().length > 1) {
+ return false;
+ }
+
+ if (!(pt.getActualTypeArguments()[0] instanceof Class)) {
+ return false;
+ }
+
+ final Class listClass = (Class) pt.getActualTypeArguments()[0];
+ return listClass == Foo.class;
+ }
+
+ @Override
+ public long getSize(List<Foo> t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(List<Foo> t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+
+ assertEquals(t, TEST_ENTITY);
+ entityStream.write(CHECK_DATA.getBytes());
+ }
+ }
+
+ @Path("root")
+ public static class RootResource {
+
+ /**
+ * Sub-resource locator is used here, so that resource model will be built
+ * at runtime, when the actual handler is the dynamic proxy.
+ *
+ * @return dynamic proxy for the sub-resource
+ */
+ @Path("sub")
+ public SubResource getSubresource() {
+ return (SubResource) Proxy.newProxyInstance(
+ RootResource.class.getClassLoader(),
+ new Class<?>[] {SubResource.class},
+ new InvocationHandler() {
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return ListProvider.TEST_ENTITY;
+ }
+ });
+ }
+ }
+
+ /**
+ * Make sure the request is processed without errors, and the data
+ * written by the {@link ListProvider} is returned back to the client.
+ */
+ @Test
+ public void testSubResourceProxy() {
+
+ final Response response = target("/root/sub").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ListProvider.CHECK_DATA, response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XXETest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XXETest.java
new file mode 100644
index 0000000..8e3d3b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XXETest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests xml security.
+ *
+ * @author Paul Sandoz
+ */
+public class XXETest extends JerseyTest {
+
+ private static final String DOCTYPE = "<!DOCTYPE foo [<!ENTITY xxe SYSTEM \"%s\">]>";
+ private static final String XML = "<jaxbBean><value>&xxe;</value></jaxbBean>";
+
+ private String getDocument() {
+ final URL u = this.getClass().getResource("xxe.txt");
+ return String.format(DOCTYPE, u.toString()) + XML;
+ }
+
+ private String getListDocument() {
+ final URL u = this.getClass().getResource("xxe.txt");
+ return String.format(DOCTYPE, u.toString()) + "<jaxbBeans>" + XML + XML + XML + "</jaxbBeans>";
+ }
+
+ @Path("/")
+ @Consumes("application/xml")
+ @Produces("application/xml")
+ public static class EntityHolderResource {
+
+ @Path("jaxb")
+ @POST
+ public String post(final JaxbBean s) {
+ return s.value;
+ }
+
+ @Path("jaxbelement")
+ @POST
+ public String post(final JAXBElement<JaxbBeanType> s) {
+ return s.getValue().value;
+ }
+
+ @Path("jaxb/list")
+ @POST
+ public String post(final List<JaxbBean> s) {
+ return s.get(0).value;
+ }
+
+ @Path("sax")
+ @POST
+ public SAXSource postSax(final SAXSource s) {
+ return s;
+ }
+
+ @Path("dom")
+ @POST
+ public String postDom(final DOMSource s) {
+ final Document d = (Document) s.getNode();
+ final Element e = (Element) d.getElementsByTagName("value").item(0);
+ final Node n = e.getChildNodes().item(0);
+ if (n.getNodeType() == Node.TEXT_NODE) {
+ return n.getNodeValue();
+ } else if (n.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ return "";
+ } else {
+ throw new WebApplicationException(400);
+ }
+ }
+
+ @Path("stream")
+ @POST
+ public StreamSource postStream(final StreamSource s) {
+ return s;
+ }
+ }
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(EntityHolderResource.class);
+ }
+
+ @Test
+ public void testJAXBSecure() {
+ final String s = target().path("jaxb").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.APPLICATION_XML_TYPE), String.class);
+ assertEquals("", s);
+ }
+
+ @Test
+ public void testJAXBSecureWithThreads() throws Throwable {
+ final int n = 4;
+ final CountDownLatch latch = new CountDownLatch(n);
+
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ final String s = target().path("jaxb").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.TEXT_PLAIN_TYPE), String.class);
+ assertEquals("", s);
+ } finally {
+ latch.countDown();
+ }
+ }
+ };
+
+ final Set<Throwable> s = new HashSet<Throwable>();
+ for (int i = 0; i < n; i++) {
+ final Thread t = new Thread(runnable);
+ t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+ public void uncaughtException(final Thread t, final Throwable ex) {
+ s.add(ex);
+ }
+ });
+ t.start();
+ }
+
+ try {
+ latch.await();
+ } catch (final InterruptedException ignored) {
+ }
+ }
+
+ @Test
+ public void testJAXBElementSecure() {
+ final String s = target().path("jaxbelement").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.APPLICATION_XML_TYPE), String.class);
+ assertEquals("", s);
+ }
+
+ @Ignore // TODO
+ @Test
+ public void testJAXBListSecure() {
+ final String s = target().path("jaxb/list").request("application/xml").post(Entity.entity(getListDocument(),
+ MediaType.APPLICATION_XML_TYPE), String.class);
+ assertEquals("", s);
+ }
+
+ @Test
+ public void testSAXSecure() {
+ final JaxbBean b = target().path("sax").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.APPLICATION_XML_TYPE), JaxbBean.class);
+ assertEquals("", b.value);
+ }
+
+ @Test
+ public void testDOMSecure() {
+ final String s = target().path("dom").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.APPLICATION_XML_TYPE), String.class);
+ assertEquals("", s);
+ }
+
+ @Test
+ public void testStreamSecure() {
+ final JaxbBean b = target().path("stream").request("application/xml").post(Entity.entity(getDocument(),
+ MediaType.APPLICATION_XML_TYPE), JaxbBean.class);
+ assertEquals("", b.value);
+ }
+
+ // NOTE - this is a tes migrated from Jersey 1.x tests. The original test class contains also insecure "versions" of the
+ // methods above configured via FeaturesAndProperties.FEATURE_DISABLE_XML_SECURITY. Those methods are ommited,
+ // as Jersey 2 does not support such consturct.
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlJaxBElementProviderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlJaxBElementProviderTest.java
new file mode 100644
index 0000000..beb84eb
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlJaxBElementProviderTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Miroslav Fuksa
+ *
+ */
+public class XmlJaxBElementProviderTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Atom.class);
+ }
+
+ @Path("atom")
+ public static class Atom {
+ @Context
+ HttpHeaders headers;
+
+ @Path("wildcard")
+ @POST
+ @Consumes("application/*")
+ @Produces("application/*")
+ public Response wildcard(JAXBElement<String> jaxb) {
+ MediaType media = headers.getMediaType();
+ return Response.ok(jaxb).type(media).build();
+ }
+
+ @Path("atom")
+ @POST
+ @Consumes("application/atom+xml")
+ @Produces("application/atom+xml")
+ public Response atom(JAXBElement<String> jaxb) {
+ MediaType media = headers.getMediaType();
+ return Response.ok(jaxb).type(media).build();
+ }
+
+ @Path("empty")
+ @POST
+ public Response emptyConsumesProduces(JAXBElement<String> jaxb) {
+ MediaType media = headers.getMediaType();
+ return Response.ok(jaxb).type(media).build();
+ }
+ }
+
+ @Test
+ public void testWildcard() {
+ final String path = "atom/wildcard";
+ _test(path);
+ }
+
+ private void _test(String path) {
+ WebTarget target = target(path);
+ final Response res = target.request("application/atom+xml").post(
+ Entity.entity(new JAXBElement<String>(new QName("atom"), String.class, "value"),
+ "application/atom+xml"));
+ assertEquals(200, res.getStatus());
+ final GenericType<JAXBElement<String>> genericType = new GenericType<JAXBElement<String>>() {};
+ final JAXBElement<String> stringJAXBElement = res.readEntity(genericType);
+ assertEquals("value", stringJAXBElement.getValue());
+ }
+
+ @Test
+ public void testAtom() {
+ final String path = "atom/atom";
+ _test(path);
+ }
+
+ @Test
+ public void testEmpty() {
+ final String path = "atom/empty";
+ _test(path);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlMoxyTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlMoxyTest.java
new file mode 100644
index 0000000..2e95ca1
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/XmlMoxyTest.java
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.namespace.QName;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@RunWith(ConcurrentRunner.class)
+public class XmlMoxyTest extends AbstractTypeTester {
+
+ @Path("JaxbBeanResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JaxbBeanResource extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentation() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanResource.class, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Path("JaxbBeanResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JaxbBeanResourceMediaType extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationMediaType() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
+ }
+
+ @Test
+ public void testJaxbBeanRepresentationError() {
+ final WebTarget target = target("JaxbBeanResource");
+
+ final String xml = "<root>foo</root>";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JaxbBeanTextResource")
+ @Produces("text/xml")
+ @Consumes("text/xml")
+ public static class JaxbBeanTextResource extends AResource<JaxbBean> {
+ }
+
+ @Test
+ public void testJaxbBeanTextRepresentation() {
+ _test(new JaxbBean("CONTENT"), JaxbBeanTextResource.class, MediaType.TEXT_XML_TYPE);
+ }
+
+ @Path("JAXBElementBeanResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBElementBeanResource extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentation() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanResource.class, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Path("JAXBElementListResource")
+ @Produces({"application/xml", "application/json"})
+ @Consumes({"application/xml", "application/json"})
+ public static class JAXBElementListResource extends AResource<List<JAXBElement<String>>> {
+ }
+
+ private List<JAXBElement<String>> getJAXBElementList() {
+ return Arrays.asList(getJAXBElementArray());
+ }
+
+ @Test
+ public void testJAXBElementListXMLRepresentation() {
+ _testListOrArray(true, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void _testListOrArray(final boolean isList, final MediaType mt) {
+ final Object in = isList ? getJAXBElementList() : getJAXBElementArray();
+ final GenericType gt = isList ? new GenericType<List<JAXBElement<String>>>() {
+ } : new GenericType<JAXBElement<String>[]>() {
+ };
+
+ final WebTarget target = target(isList ? "JAXBElementListResource" : "JAXBElementArrayResource");
+ final Object out = target.request(mt).post(Entity.entity(new GenericEntity(in, gt.getType()), mt), gt);
+
+ final List<JAXBElement<String>> inList =
+ isList ? ((List<JAXBElement<String>>) in) : Arrays.asList((JAXBElement<String>[]) in);
+ final List<JAXBElement<String>> outList = isList ? ((List<JAXBElement<String>>) out) : Arrays
+ .asList((JAXBElement<String>[]) out);
+ assertEquals("Lengths differ", inList.size(), outList.size());
+ for (int i = 0; i < inList.size(); i++) {
+ assertEquals("Names of elements at index " + i + " differ", inList.get(i).getName(), outList.get(i).getName());
+ assertEquals("Values of elements at index " + i + " differ", inList.get(i).getValue(), outList.get(i).getValue());
+ }
+ }
+
+ @Path("JAXBElementArrayResource")
+ @Produces({"application/xml", "application/json"})
+ @Consumes({"application/xml", "application/json"})
+ public static class JAXBElementArrayResource extends AResource<JAXBElement<String>[]> {
+ }
+
+ private JAXBElement<String>[] getJAXBElementArray() {
+ //noinspection unchecked
+ return new JAXBElement[] {
+ new JAXBElement(QName.valueOf("element1"), String.class, "ahoj"),
+ new JAXBElement(QName.valueOf("element2"), String.class, "nazdar")
+ };
+ }
+
+ @Test
+ public void testJAXBElementArrayXMLRepresentation() {
+ _testListOrArray(false, MediaType.APPLICATION_XML_TYPE);
+ }
+
+ @Path("JAXBElementBeanResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBElementBeanResourceMediaType extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationMediaType() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
+ }
+
+ @Test
+ public void testJAXBElementBeanRepresentationError() {
+ final WebTarget target = target("JAXBElementBeanResource");
+
+ final String xml = "<root><value>foo";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JAXBElementBeanTextResource")
+ @Produces("text/xml")
+ @Consumes("text/xml")
+ public static class JAXBElementBeanTextResource extends AResource<JAXBElement<JaxbBeanType>> {
+ }
+
+ @Test
+ public void testJAXBElementBeanTextRepresentation() {
+ _test(new JaxbBean("CONTENT"), JAXBElementBeanTextResource.class, MediaType.TEXT_XML_TYPE);
+ }
+
+ @Path("JAXBTypeResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBTypeResource {
+
+ @POST
+ public JaxbBean post(final JaxbBeanType t) {
+ return new JaxbBean(t.value);
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return ((ResourceConfig) super.configure()).register(new MoxyXmlFeature(SimpleBean.class));
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+ config.register(new MoxyXmlFeature(SimpleBean.class));
+ }
+
+ @Test
+ public void testJAXBTypeRepresentation() {
+ final WebTarget target = target("JAXBTypeResource");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/xml"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBTypeResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBTypeResourceMediaType extends JAXBTypeResource {
+ }
+
+ @Test
+ public void testJAXBTypeRepresentationMediaType() {
+ final WebTarget target = target("JAXBTypeResourceMediaType");
+ final JaxbBean in = new JaxbBean("CONTENT");
+ final JaxbBeanType out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBeanType.class);
+ assertEquals(in.value, out.value);
+ }
+
+ @Path("JAXBObjectResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBObjectResource {
+
+ @POST
+ public Object post(final Object o) {
+ return o;
+ }
+ }
+
+ @Provider
+ public static class JAXBObjectResolver implements ContextResolver<JAXBContext> {
+
+ public JAXBContext getContext(final Class<?> c) {
+ if (Object.class == c) {
+ try {
+ return JAXBContext.newInstance(JaxbBean.class);
+ } catch (final JAXBException ex) {
+ // NOOP.
+ }
+ }
+ return null;
+ }
+ }
+
+ @Test
+ public void testJAXBObjectRepresentation() {
+ final WebTarget target = target("JAXBObjectResource");
+ final Object in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/xml"), JaxbBean.class);
+ assertEquals(in, out);
+ }
+
+ @Path("JAXBObjectResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBObjectResourceMediaType extends JAXBObjectResource {
+ }
+
+ @Test
+ public void testJAXBObjectRepresentationMediaType() {
+ final WebTarget target = target("JAXBObjectResourceMediaType");
+ final Object in = new JaxbBean("CONTENT");
+ final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBean.class);
+ assertEquals(in, out);
+ }
+
+ @Test
+ public void testJAXBObjectRepresentationError() {
+ final WebTarget target = target("JAXBObjectResource");
+
+ final String xml = "<root>foo</root>";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Path("JAXBListResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBListResource {
+
+ @POST
+ public List<JaxbBean> post(final List<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("set")
+ public Set<JaxbBean> postSet(final Set<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("queue")
+ public Queue<JaxbBean> postQueue(final Queue<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("stack")
+ public Stack<JaxbBean> postStack(final Stack<JaxbBean> l) {
+ return l;
+ }
+
+ @POST
+ @Path("custom")
+ public MyArrayList<JaxbBean> postCustom(final MyArrayList<JaxbBean> l) {
+ return l;
+ }
+
+ @GET
+ public Collection<JaxbBean> get() {
+ final ArrayList<JaxbBean> l = new ArrayList<>();
+ l.add(new JaxbBean("one"));
+ l.add(new JaxbBean("two"));
+ l.add(new JaxbBean("three"));
+ return l;
+ }
+
+ @POST
+ @Path("type")
+ public List<JaxbBean> postType(final Collection<JaxbBeanType> l) {
+ final List<JaxbBean> beans = new ArrayList<>();
+ for (final JaxbBeanType t : l) {
+ beans.add(new JaxbBean(t.value));
+ }
+ return beans;
+ }
+ }
+
+ @Path("JAXBArrayResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class JAXBArrayResource {
+
+ @POST
+ public JaxbBean[] post(final JaxbBean[] l) {
+ return l;
+ }
+
+ @GET
+ public JaxbBean[] get() {
+ final ArrayList<JaxbBean> l = new ArrayList<>();
+ l.add(new JaxbBean("one"));
+ l.add(new JaxbBean("two"));
+ l.add(new JaxbBean("three"));
+ return l.toArray(new JaxbBean[l.size()]);
+ }
+
+ @POST
+ @Path("type")
+ public JaxbBean[] postType(final JaxbBeanType[] l) {
+ final List<JaxbBean> beans = new ArrayList<>();
+ for (final JaxbBeanType t : l) {
+ beans.add(new JaxbBean(t.value));
+ }
+ return beans.toArray(new JaxbBean[beans.size()]);
+ }
+ }
+
+ @Test
+ public void testJAXBArrayRepresentation() {
+ final WebTarget target = target("JAXBArrayResource");
+
+ final JaxbBean[] a = target.request().get(JaxbBean[].class);
+ JaxbBean[] b = target.request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
+ assertEquals(a.length, b.length);
+ for (int i = 0; i < a.length; i++) {
+ assertEquals(a[i], b[i]);
+ }
+
+ b = target.path("type").request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
+ assertEquals(a.length, b.length);
+ for (int i = 0; i < a.length; i++) {
+ assertEquals(a[i], b[i]);
+ }
+ }
+
+ @Path("JAXBListResourceMediaType")
+ @Produces("application/foo+xml")
+ @Consumes("application/foo+xml")
+ public static class JAXBListResourceMediaType extends JAXBListResource {
+ }
+
+ @Test
+ public void testJAXBListRepresentationMediaType() {
+ final WebTarget target = target("JAXBListResourceMediaType");
+
+ Collection<JaxbBean> a = target.request().get(
+ new GenericType<Collection<JaxbBean>>() {
+ });
+ Collection<JaxbBean> b = target.request()
+ .post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {}, "application/foo+xml"),
+ new GenericType<Collection<JaxbBean>>() {});
+
+ assertEquals(a, b);
+
+ b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
+ }, "application/foo+xml"), new GenericType<Collection<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new LinkedList<>(a);
+ b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<Queue<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+
+ a = new HashSet<>(a);
+ b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<Set<JaxbBean>>() {
+ });
+ final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
+ @Override
+ public int compare(final JaxbBean t, final JaxbBean t1) {
+ return t.value.compareTo(t1.value);
+ }
+ };
+ final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
+ final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
+ t1.addAll(a);
+ t2.addAll(b);
+ assertEquals(t1, t2);
+
+ final Stack<JaxbBean> s = new Stack<>();
+ s.addAll(a);
+ b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
+ }, "application/foo+xml"), new GenericType<Stack<JaxbBean>>() {
+ });
+ assertEquals(s, b);
+
+ a = new MyArrayList<>(a);
+ b = target.path("custom").request()
+ .post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {
+ }, "application/foo+xml"), new GenericType<MyArrayList<JaxbBean>>() {
+ });
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testJAXBListRepresentationError() {
+ final WebTarget target = target("JAXBListResource");
+
+ final String xml = "<root><value>foo";
+ final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public static class SimpleBean {
+
+ private String value;
+
+ public SimpleBean() {
+ }
+
+ public SimpleBean(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ @XmlRootElement
+ public static class ComplexJaxbBean {
+
+ private Object simpleBean;
+
+ public ComplexJaxbBean() {
+ }
+
+ public ComplexJaxbBean(final Object simpleBean) {
+ this.simpleBean = simpleBean;
+ }
+
+ public Object getSimpleBean() {
+ return simpleBean;
+ }
+
+ public void setSimpleBean(final Object simpleBean) {
+ this.simpleBean = simpleBean;
+ }
+ }
+
+ @Path("AdditionalClassesResource")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public static class AdditionalClassesResource {
+
+ @GET
+ public ComplexJaxbBean get() {
+ return new ComplexJaxbBean(new SimpleBean("foo"));
+ }
+ }
+
+ @Test
+ public void testAdditionalClasses() throws Exception {
+ final ComplexJaxbBean nonJaxbBean = target("AdditionalClassesResource").request().get(ComplexJaxbBean.class);
+ final Object simpleBean = nonJaxbBean.getSimpleBean();
+
+ assertThat(simpleBean, notNullValue());
+ assertThat(simpleBean, instanceOf(SimpleBean.class));
+ assertThat("foo", equalTo(((SimpleBean) simpleBean).getValue()));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/DefaultFilteringScope.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/DefaultFilteringScope.java
new file mode 100644
index 0000000..fd630b5
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/DefaultFilteringScope.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * @author Michal Gajdos
+ */
+public class DefaultFilteringScope extends AnnotationLiteral<EntityFiltering> implements EntityFiltering {
+
+ /**
+ * Get an instance of {@link EntityFiltering} annotation.
+ */
+ public DefaultFilteringScope() {
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EmptyEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EmptyEntityTest.java
new file mode 100644
index 0000000..43c3562
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EmptyEntityTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.EmptyEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.NonEmptyEntity;
+
+import org.junit.Test;
+
+/**
+ * Use-cases to check whether empty class causes problems (JERSEY-2824 reproducer).
+ *
+ * @author Michal Gajdos
+ */
+public class EmptyEntityTest extends EntityFilteringTest {
+
+ @Path("/")
+ @Consumes("entity/filtering")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @Path("nonEmptyEntity")
+ @GET
+ public NonEmptyEntity nonEmptyEntity() {
+ return NonEmptyEntity.INSTANCE;
+ }
+
+ @Path("emptyEntity")
+ @GET
+ public EmptyEntity emptyEntity() {
+ return new EmptyEntity();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class)
+ // Providers.
+ .register(EntityFilteringFeature.class)
+ .register(FilteringMessageBodyProvider.class);
+ }
+
+ @Test
+ public void testNonEmptyEntity() throws Exception {
+ final String fields = target("nonEmptyEntity").request().get(String.class);
+
+ assertSameFields(fields, "value");
+ }
+
+ @Test
+ public void testEmptyEntity() throws Exception {
+ final String fields = target("emptyEntity").request().get(String.class);
+
+ assertSameFields(fields, "");
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringClientTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringClientTest.java
new file mode 100644
index 0000000..1605035
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringClientTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnClassEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(ConcurrentRunner.class)
+public class EntityFilteringClientTest extends EntityFilteringTest {
+
+ public static final MediaType ENTITY_FILTERING = new MediaType("entity", "filtering");
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(EntityFilteringFeature.class).register(FilteringMessageBodyProvider.class);
+ }
+
+ @Path("/")
+ @Consumes("entity/filtering")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @POST
+ public String post(final String value) {
+ return value;
+ }
+ }
+
+ @Test
+ public void testEntityAnnotationsPrimaryView() throws Exception {
+ final String fields = target()
+ .request()
+ .post(Entity.entity(
+ new OneFilteringOnClassEntity(),
+ ENTITY_FILTERING,
+ new Annotation[] {PrimaryDetailedView.Factory.get()}),
+ String.class);
+
+ assertSameFields(fields, "field,accessor,property,subEntities.field2,subEntities.property2,subEntities.property1,"
+ + "subEntities.field1,defaultEntities.field,defaultEntities.property");
+ }
+
+ @Test
+ public void testEntityAnnotationsDefaultView() throws Exception {
+ final String fields = target()
+ .request()
+ .post(Entity.entity(new OneFilteringOnClassEntity(),
+ ENTITY_FILTERING,
+ new Annotation[] {new DefaultFilteringScope()}),
+ String.class);
+
+ assertThat(fields, equalTo(""));
+ }
+
+ @Test
+ public void testEntityAnnotationsInvalidView() throws Exception {
+ final String fields = target()
+ .request()
+ .post(Entity.entity(
+ new OneFilteringOnClassEntity(),
+ ENTITY_FILTERING,
+ new Annotation[] {CustomAnnotationLiteral.INSTANCE}),
+ String.class);
+
+ assertThat(fields, equalTo(""));
+ }
+
+ @Test
+ public void testConfigurationPrimaryView() throws Exception {
+ testConfiguration("field,accessor,property,subEntities.field2,subEntities.property2,subEntities.property1,"
+ + "subEntities.field1,defaultEntities.field,defaultEntities.property", PrimaryDetailedView.Factory.get());
+ }
+
+ @Test
+ public void testConfigurationDefaultView() throws Exception {
+ testConfiguration("", new DefaultFilteringScope());
+ }
+
+ @Test
+ public void testConfigurationMultipleViews() throws Exception {
+ testConfiguration("field,accessor,property,subEntities.field2,subEntities.property2,subEntities.property1,"
+ + "subEntities.field1,defaultEntities.field,defaultEntities.property", PrimaryDetailedView.Factory.get(),
+ CustomAnnotationLiteral.INSTANCE);
+ }
+
+ private void testConfiguration(final String expected, final Annotation... annotations) {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, annotations.length == 1 ? annotations[0] : annotations);
+ configureClient(config);
+
+ final String fields = ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(new OneFilteringOnClassEntity(), ENTITY_FILTERING), String.class);
+
+ assertSameFields(fields, expected);
+ }
+
+ @Test
+ public void testInvalidConfiguration() throws Exception {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, "invalid_value");
+ configureClient(config);
+
+ final String fields =
+ ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(new OneFilteringOnClassEntity(), ENTITY_FILTERING), String.class);
+
+ assertThat(fields, equalTo(""));
+ }
+
+ @Test
+ public void testEntityAnnotationsOverConfiguration() throws Exception {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, SecondaryDetailedView.Factory.get());
+ configureClient(config);
+
+ final String fields = ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(
+ new ManyFilteringsOnClassEntity(),
+ ENTITY_FILTERING,
+ new Annotation[] {PrimaryDetailedView.Factory.get()}),
+ String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnClassTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnClassTest.java
new file mode 100644
index 0000000..912c24d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnClassTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnClassEntity;
+
+import org.junit.Test;
+
+/**
+ * Use-cases with entity-filtering annotations on class.
+ *
+ * @author Michal Gajdos
+ */
+public class EntityFilteringOnClassTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class)
+ // Providers.
+ .register(EntityFilteringFeature.class)
+ .register(FilteringMessageBodyProvider.class);
+ }
+
+ @Path("/")
+ @Consumes("entity/filtering")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @GET
+ @Path("OneFilteringEntity")
+ @PrimaryDetailedView
+ public OneFilteringOnClassEntity getOneFilteringEntity() {
+ return new OneFilteringOnClassEntity();
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultView")
+ public OneFilteringOnClassEntity getOneFilteringEntityDefaultView() {
+ return new OneFilteringOnClassEntity();
+ }
+
+ @POST
+ @Path("OneFilteringEntity")
+ public String postOneFilteringEntity(final String value) {
+ return value;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultViewResponse")
+ public Response getOneFilteringEntityDefaultViewResponse() {
+ return Response.ok().entity(new OneFilteringOnClassEntity(), new Annotation[] {new DefaultFilteringScope()}).build();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityPrimaryView")
+ @PrimaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityPrimaryView() {
+ return new ManyFilteringsOnClassEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntitySecondaryView")
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntitySecondaryView() {
+ return new ManyFilteringsOnClassEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityDefaultView")
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityDefaultView() {
+ return new ManyFilteringsOnClassEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityManyViews")
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityManyViews() {
+ return new ManyFilteringsOnClassEntity();
+ }
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClass() throws Exception {
+ final String fields = target("OneFilteringEntity").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,subEntities.field2,subEntities.property2,subEntities.property1,"
+ + "subEntities.field1,defaultEntities.field,defaultEntities.property");
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClassDefaultViewResponse() throws Exception {
+ final String fields = target("OneFilteringEntityDefaultViewResponse").request().get(String.class);
+
+ assertSameFields(fields, "");
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClassDefaultView() throws Exception {
+ final String fields = target("OneFilteringEntityDefaultView").request().get(String.class);
+
+ assertSameFields(fields, "");
+ }
+
+ @Test
+ public void testMultipleViewsOnClass() throws Exception {
+ testOneEntityFilteringOnClass();
+ testOneEntityFilteringOnClassDefaultView();
+ }
+
+ @Test
+ public void testManyFilteringsEntityPrimaryView() throws Exception {
+ final String fields = target("ManyFilteringsEntityPrimaryView").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+
+ @Test
+ public void testManyFilteringsEntitySecondaryView() throws Exception {
+ final String fields = target("ManyFilteringsEntitySecondaryView").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.field2,manyEntities.property2,manyEntities.field1,"
+ + "oneEntities.property2,oneEntities.field1,defaultEntities.field,defaultEntities.property");
+ }
+
+ @Test
+ public void testManyFilteringsEntityDefaultView() throws Exception {
+ final String fields = target("ManyFilteringsEntityDefaultView").request().get(String.class);
+
+ assertSameFields(fields, "");
+ }
+
+ @Test
+ public void testManyFilteringsEntityManyViews() throws Exception {
+ final String fields = target("ManyFilteringsEntityManyViews").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.field2,manyEntities.property2,manyEntities.property1,"
+ + "manyEntities.field1,oneEntities.field2,oneEntities.property2,oneEntities.property1,oneEntities.field1,"
+ + "defaultEntities.field,defaultEntities.property");
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnPropertiesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnPropertiesTest.java
new file mode 100644
index 0000000..22603ab
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringOnPropertiesTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnPropertiesEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnPropertiesEntity;
+
+import org.junit.Test;
+
+/**
+ * Use-cases with entity-filtering annotations on properties.
+ *
+ * @author Michal Gajdos
+ */
+public class EntityFilteringOnPropertiesTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class)
+ // Providers.
+ .register(EntityFilteringFeature.class)
+ .register(FilteringMessageBodyProvider.class);
+ }
+
+ @Path("/")
+ @Consumes("entity/filtering")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @GET
+ @Path("OneFilteringEntity")
+ @PrimaryDetailedView
+ public OneFilteringOnPropertiesEntity getOneFilteringEntity() {
+ return new OneFilteringOnPropertiesEntity();
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultView")
+ public OneFilteringOnPropertiesEntity getOneFilteringEntityDefaultView() {
+ return new OneFilteringOnPropertiesEntity();
+ }
+
+ @POST
+ @Path("OneFilteringEntity")
+ public String postOneFilteringEntity(final String value) {
+ return value;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultViewResponse")
+ public Response getOneFilteringEntityDefaultViewResponse() {
+ return Response.ok().entity(new OneFilteringOnPropertiesEntity(), new Annotation[] {new DefaultFilteringScope()})
+ .build();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityPrimaryView")
+ @PrimaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityPrimaryView() {
+ return new ManyFilteringsOnPropertiesEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntitySecondaryView")
+ @SecondaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntitySecondaryView() {
+ return new ManyFilteringsOnPropertiesEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityDefaultView")
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityDefaultView() {
+ return new ManyFilteringsOnPropertiesEntity();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityManyViews")
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityManyViews() {
+ return new ManyFilteringsOnPropertiesEntity();
+ }
+ }
+
+ @Test
+ public void testOneEntityFilteringOnProperties() throws Exception {
+ final String fields = target("OneFilteringEntity").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,subEntities.field2,subEntities.property2,subEntities.property1,"
+ + "subEntities.field1,defaultEntities.field,defaultEntities.property");
+ }
+
+ @Test
+ public void testOneEntityFilteringOnPropertiesDefaultViewResponse() throws Exception {
+ final String fields = target("OneFilteringEntityDefaultViewResponse").request().get(String.class);
+
+ assertSameFields(fields, "field");
+ }
+
+ @Test
+ public void testOneEntityFilteringOnPropertiesDefaultView() throws Exception {
+ final String fields = target("OneFilteringEntityDefaultView").request().get(String.class);
+
+ assertSameFields(fields, "field");
+ }
+
+ @Test
+ public void testManyFilteringsEntityPrimaryView() throws Exception {
+ final String fields = target("ManyFilteringsEntityPrimaryView").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,oneEntities.field2,oneEntities.property2,oneEntities.property1,"
+ + "oneEntities.field1,defaultEntities.field,defaultEntities.property");
+ }
+
+ @Test
+ public void testManyFilteringsEntitySecondaryView() throws Exception {
+ final String fields = target("ManyFilteringsEntitySecondaryView").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.field2,manyEntities.property2,manyEntities.field1,"
+ + "oneEntities.property2,oneEntities.field1");
+ }
+
+ @Test
+ public void testManyFilteringsEntityDefaultView() throws Exception {
+ final String fields = target("ManyFilteringsEntityDefaultView").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor");
+ }
+
+ @Test
+ public void testManyFilteringsEntityManyViews() throws Exception {
+ final String fields = target("ManyFilteringsEntityManyViews").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.field2,manyEntities.property2,manyEntities.property1,"
+ + "manyEntities.field1,oneEntities.field2,oneEntities.property2,oneEntities.property1,oneEntities.field1,"
+ + "defaultEntities.field,defaultEntities.property");
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringScopesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringScopesTest.java
new file mode 100644
index 0000000..5f910fb
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringScopesTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ComplexEntity;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EntityFilteringScopesTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class)
+ // Providers.
+ .register(EntityFilteringFeature.class)
+ .register(FilteringMessageBodyProvider.class);
+ }
+
+ @Path("/")
+ @Consumes("entity/filtering")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @GET
+ @PrimaryDetailedView
+ public ComplexEntity get() {
+ return new ComplexEntity();
+ }
+ }
+
+ /**
+ * Primary -> Default -> Primary.
+ */
+ @Test
+ public void testEntityFilteringScopes() throws Exception {
+ final String fields = target().request().get(String.class);
+
+ assertSameFields(fields, "accessor,property,field.field,field.accessor,field.property.accessor,field.property.property");
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringServerTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringServerTest.java
new file mode 100644
index 0000000..4d8303b
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringServerTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ EntityFilteringServerTest.ConfigurationServerTest.class,
+ EntityFilteringServerTest.ConfigurationDefaultViewServerTest.class,
+ EntityFilteringServerTest.AnnotationsServerTest.class,
+ EntityFilteringServerTest.AnnotationsOverConfigurationServerTest.class
+})
+public class EntityFilteringServerTest {
+
+ @Path("/")
+ @Produces("entity/filtering")
+ public static class Resource {
+
+ @GET
+ @Path("configuration")
+ public ManyFilteringsOnClassEntity getConfiguration() {
+ return new ManyFilteringsOnClassEntity();
+ }
+
+ @GET
+ @Path("configurationOverResource")
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getConfigurationOverResource() {
+ return new ManyFilteringsOnClassEntity();
+ }
+
+ @GET
+ @Path("annotations")
+ public Response getAnnotations() {
+ return Response
+ .ok()
+ .entity(new ManyFilteringsOnClassEntity(), new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverConfiguration")
+ public Response getAnnotationsOverConfiguration() {
+ return Response
+ .ok()
+ .entity(new ManyFilteringsOnClassEntity(), new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverResource")
+ @SecondaryDetailedView
+ public Response getAnnotationsOverResource() {
+ return Response
+ .ok()
+ .entity(new ManyFilteringsOnClassEntity(), new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverConfigurationOverResource")
+ @SecondaryDetailedView
+ public Response getAnnotationsOverConfigurationOverResource() {
+ return Response
+ .ok()
+ .entity(new ManyFilteringsOnClassEntity(), new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+ }
+
+ private static class FilteringResourceConfig extends ResourceConfig {
+
+ private FilteringResourceConfig() {
+ // Resources.
+ register(Resource.class);
+
+ // Providers.
+ register(EntityFilteringFeature.class);
+ register(FilteringMessageBodyProvider.class);
+ }
+ }
+
+ public static class ConfigurationServerTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new FilteringResourceConfig()
+ // Properties
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, PrimaryDetailedView.Factory.get());
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+ final String fields = target("configuration").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+
+ @Test
+ public void testConfigurationOverResource() throws Exception {
+ final String fields = target("configurationOverResource").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+ }
+
+ public static class ConfigurationDefaultViewServerTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new FilteringResourceConfig();
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+ final String fields = target("configuration").request().get(String.class);
+
+ assertSameFields(fields, "");
+ }
+ }
+
+ public static class AnnotationsServerTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new FilteringResourceConfig();
+ }
+
+ @Test
+ public void testAnnotations() throws Exception {
+ final String fields = target("annotations").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+
+ @Test
+ public void testAnnotationsOverResource() throws Exception {
+ final String fields = target("annotationsOverResource").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+ }
+
+ public static class AnnotationsOverConfigurationServerTest extends EntityFilteringTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new FilteringResourceConfig()
+ // Properties
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new DefaultFilteringScope());
+ }
+
+ @Test
+ public void testAnnotationsOverConfiguration() throws Exception {
+ final String fields = target("annotationsOverConfiguration").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+
+ @Test
+ public void testAnnotationsOverConfigurationOverResource() throws Exception {
+ final String fields = target("annotationsOverConfigurationOverResource").request().get(String.class);
+
+ assertSameFields(fields, "field,accessor,property,manyEntities.property1,manyEntities.field1,oneEntities.field2,"
+ + "oneEntities.property2,oneEntities.property1,oneEntities.field1,defaultEntities.field,defaultEntities"
+ + ".property");
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringTest.java
new file mode 100644
index 0000000..b450e0c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/EntityFilteringTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.glassfish.jersey.test.JerseyTest;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Common parent class for Entity Filtering tests.
+ *
+ * @author Michal Gajdos
+ */
+abstract class EntityFilteringTest extends JerseyTest {
+
+ /**
+ * Test that (filtered) fields of given strings are equal (fields are separated by commas).
+ *
+ * @param actual actual fields from response received from server.
+ * @param expected expected fields.
+ */
+ static void assertSameFields(final String actual, final String expected) {
+ final Set<String> actualSet = Arrays.stream(actual.split(",")).collect(Collectors.toSet());
+ final Set<String> expectedSet = Arrays.stream(expected.split(",")).collect(Collectors.toSet());
+
+ assertThat(actualSet, equalTo(expectedSet));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java
new file mode 100644
index 0000000..dcb6ba5
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.message.filtering.spi.FilteringHelper;
+import org.glassfish.jersey.message.filtering.spi.ObjectGraph;
+import org.glassfish.jersey.message.filtering.spi.ObjectProvider;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+@Consumes("entity/filtering")
+@Produces("entity/filtering")
+public class FilteringMessageBodyProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> {
+
+ private static final Logger LOGGER = Logger.getLogger(FilteringMessageBodyProvider.class.getName());
+
+ @Inject
+ private javax.inject.Provider<ObjectProvider<ObjectGraph>> provider;
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return String.class != type;
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return String.class != type;
+ }
+
+ @Override
+ public long getSize(final Object o, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public Object readFrom(final Class<Object> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ try {
+ final ObjectGraph objectGraph = provider.get()
+ .getFilteringObject(FilteringHelper.getEntityClass(genericType), false, annotations);
+
+ return objectGraphToString(objectGraph);
+ } catch (final Throwable t) {
+ LOGGER.log(Level.WARNING, "Error during reading an object graph.", t);
+ return "ERROR: " + t.getMessage();
+ }
+ }
+
+ @Override
+ public void writeTo(final Object o, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ final ObjectGraph objectGraph = provider.get()
+ .getFilteringObject(FilteringHelper.getEntityClass(genericType), true, annotations);
+
+ try {
+ entityStream.write(objectGraphToString(objectGraph).getBytes());
+ } catch (final Throwable t) {
+ LOGGER.log(Level.WARNING, "Error during writing an object graph.", t);
+ }
+ }
+
+ private static String objectGraphToString(final ObjectGraph objectGraph) {
+ final StringBuilder sb = new StringBuilder();
+ for (final String field : objectGraphToFields("", objectGraph)) {
+ if (!field.contains("Transient")) {
+ sb.append(field).append(',');
+ }
+ }
+ if (sb.length() > 0) {
+ sb.delete(sb.length() - 1, sb.length());
+ }
+ return sb.toString();
+ }
+
+ private static List<String> objectGraphToFields(final String prefix, final ObjectGraph objectGraph) {
+ final List<String> fields = new ArrayList<>();
+
+ // Fields.
+ for (final String field : objectGraph.getFields()) {
+ fields.add(prefix + field);
+ }
+
+ for (final Map.Entry<String, ObjectGraph> entry : objectGraph.getSubgraphs().entrySet()) {
+ fields.addAll(objectGraphToFields(prefix + entry.getKey() + ".", entry.getValue()));
+ }
+
+ return fields;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/PrimaryDetailedView.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/PrimaryDetailedView.java
new file mode 100644
index 0000000..340a343
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/PrimaryDetailedView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface PrimaryDetailedView {
+
+ public static class Factory extends AnnotationLiteral<PrimaryDetailedView> implements PrimaryDetailedView {
+
+ private Factory() {
+ }
+
+ public static PrimaryDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/SecondaryDetailedView.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/SecondaryDetailedView.java
new file mode 100644
index 0000000..8bd206f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/SecondaryDetailedView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface SecondaryDetailedView {
+
+ public static class Factory extends AnnotationLiteral<SecondaryDetailedView> implements SecondaryDetailedView {
+
+ private Factory() {
+ }
+
+ public static SecondaryDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/TertiaryDetailedView.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/TertiaryDetailedView.java
new file mode 100644
index 0000000..3b9a512
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/TertiaryDetailedView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface TertiaryDetailedView {
+
+ public static class Factory extends AnnotationLiteral<TertiaryDetailedView> implements TertiaryDetailedView {
+
+ private Factory() {
+ }
+
+ public static TertiaryDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexEntity.java
new file mode 100644
index 0000000..a6a36a2
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexEntity.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Primary detailed view ONLY.
+ *
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+// Entity Filtering.
+@PrimaryDetailedView
+public class ComplexEntity {
+
+ public static final ComplexEntity INSTANCE;
+
+ static {
+ INSTANCE = new ComplexEntity();
+ INSTANCE.field = ComplexSubEntity.INSTANCE;
+ INSTANCE.property = "property";
+ }
+
+ @XmlElement
+ public ComplexSubEntity field;
+
+ private String property;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ public String getAccessor() {
+ return accessorTransient == null ? property + property : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubEntity.java
new file mode 100644
index 0000000..7676e3c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubEntity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Default view ONLY.
+ *
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class ComplexSubEntity {
+
+ public static final ComplexSubEntity INSTANCE;
+
+ static {
+ INSTANCE = new ComplexSubEntity();
+ INSTANCE.field = "field";
+ INSTANCE.property = ComplexSubSubEntity.INSTANCE;
+ }
+
+ @XmlElement
+ public String field;
+
+ private ComplexSubSubEntity property;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ public ComplexSubSubEntity getProperty() {
+ return property;
+ }
+
+ public void setProperty(final ComplexSubSubEntity property) {
+ this.property = property;
+ }
+
+ public String getAccessor() {
+ return accessorTransient == null ? field + field : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubSubEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubSubEntity.java
new file mode 100644
index 0000000..be709e0
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ComplexSubSubEntity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Mixed views.
+ *
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class ComplexSubSubEntity {
+
+ public static final ComplexSubSubEntity INSTANCE;
+
+ static {
+ INSTANCE = new ComplexSubSubEntity();
+ INSTANCE.field = "field";
+ INSTANCE.property = "property";
+ }
+
+ @XmlElement
+ @SecondaryDetailedView
+ public String field;
+
+ private String property;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ @PrimaryDetailedView
+ public String getAccessor() {
+ return accessorTransient == null ? field + field : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/DefaultFilteringSubEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/DefaultFilteringSubEntity.java
new file mode 100644
index 0000000..fcd3888
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/DefaultFilteringSubEntity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+
+/**
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class DefaultFilteringSubEntity {
+
+ public static final DefaultFilteringSubEntity INSTANCE;
+
+ static {
+ INSTANCE = new DefaultFilteringSubEntity();
+ INSTANCE.field = true;
+ INSTANCE.property = 20L;
+ }
+
+ @XmlElement
+ public boolean field;
+ private Long property;
+
+ public Long getProperty() {
+ return property;
+ }
+
+ public void setProperty(final Long property) {
+ this.property = property;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/EmptyEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/EmptyEntity.java
new file mode 100644
index 0000000..7e8389c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/EmptyEntity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyEntity {
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/FilteredClassEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/FilteredClassEntity.java
new file mode 100644
index 0000000..b1ec5f8
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/FilteredClassEntity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.TertiaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+
+/**
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+// Entity Filtering.
+@TertiaryDetailedView
+public class FilteredClassEntity {
+
+ public static final FilteredClassEntity INSTANCE;
+
+ static {
+ INSTANCE = new FilteredClassEntity();
+ INSTANCE.field = 40;
+ INSTANCE.property = "property";
+ }
+
+ @XmlElement
+ public int field;
+ private String property;
+
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnClassEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnClassEntity.java
new file mode 100644
index 0000000..8221fb9
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnClassEntity.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+// Entity Filtering.
+@PrimaryDetailedView
+@SecondaryDetailedView
+public class ManyFilteringsOnClassEntity {
+
+ public static final ManyFilteringsOnClassEntity INSTANCE;
+
+ static {
+ INSTANCE = new ManyFilteringsOnClassEntity();
+ INSTANCE.field = 50;
+ INSTANCE.property = "property";
+ INSTANCE.defaultEntities = Collections.singletonList(DefaultFilteringSubEntity.INSTANCE);
+ INSTANCE.oneEntities = Collections.singletonList(OneFilteringSubEntity.INSTANCE);
+ INSTANCE.manyEntities = Collections.singletonList(ManyFilteringsSubEntity.INSTANCE);
+ INSTANCE.filtered = FilteredClassEntity.INSTANCE;
+ }
+
+ @XmlElement
+ public int field;
+ private String property;
+
+ @XmlElement
+ public List<DefaultFilteringSubEntity> defaultEntities;
+
+ @XmlElement
+ public List<OneFilteringSubEntity> oneEntities;
+ @XmlElement
+ public List<ManyFilteringsSubEntity> manyEntities;
+
+ @XmlElement
+ public FilteredClassEntity filtered;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ public String getAccessor() {
+ return accessorTransient == null ? property + property : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnPropertiesEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnPropertiesEntity.java
new file mode 100644
index 0000000..f59b87d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsOnPropertiesEntity.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * @author Michal Gajdos
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class ManyFilteringsOnPropertiesEntity {
+
+ public static final ManyFilteringsOnPropertiesEntity INSTANCE;
+
+ static {
+ INSTANCE = new ManyFilteringsOnPropertiesEntity();
+ INSTANCE.field = 90;
+ INSTANCE.property = "property";
+ INSTANCE.defaultEntities = Collections.singletonList(DefaultFilteringSubEntity.INSTANCE);
+ INSTANCE.oneEntities = Collections.singletonList(OneFilteringSubEntity.INSTANCE);
+ INSTANCE.manyEntities = Collections.singletonList(ManyFilteringsSubEntity.INSTANCE);
+ INSTANCE.filtered = FilteredClassEntity.INSTANCE;
+ }
+
+ @XmlElement
+ public int field;
+ private String property;
+
+ @XmlElement
+ @PrimaryDetailedView
+ public List<DefaultFilteringSubEntity> defaultEntities;
+
+ @XmlElement
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public List<OneFilteringSubEntity> oneEntities;
+
+ @XmlElement
+ @SecondaryDetailedView
+ public List<ManyFilteringsSubEntity> manyEntities;
+
+ @XmlElement
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public FilteredClassEntity filtered;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ public String getAccessor() {
+ return accessorTransient == null ? property + property : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsSubEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsSubEntity.java
new file mode 100644
index 0000000..b326abc
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/ManyFilteringsSubEntity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+
+/**
+* @author Michal Gajdos
+*/
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class ManyFilteringsSubEntity {
+
+ public static final ManyFilteringsSubEntity INSTANCE;
+
+ static {
+ INSTANCE = new ManyFilteringsSubEntity();
+ INSTANCE.field1 = 60;
+ INSTANCE.field2 = 70;
+ INSTANCE.property1 = "property1";
+ INSTANCE.property2 = "property2";
+ }
+
+ @XmlElement
+ public int field1;
+
+ @XmlElement
+ @SecondaryDetailedView
+ public int field2;
+
+ private String property1;
+ private String property2;
+
+ @PrimaryDetailedView
+ public String getProperty1() {
+ return property1;
+ }
+
+ public void setProperty1(final String property1) {
+ this.property1 = property1;
+ }
+
+ @SecondaryDetailedView
+ public String getProperty2() {
+ return property2;
+ }
+
+ @PrimaryDetailedView
+ public void setProperty2(final String property2) {
+ this.property2 = property2;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/NonEmptyEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/NonEmptyEntity.java
new file mode 100644
index 0000000..78f0098
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/NonEmptyEntity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+/**
+ * @author Michal Gajdos
+ */
+public class NonEmptyEntity {
+
+ public static final NonEmptyEntity INSTANCE;
+
+ static {
+ INSTANCE = new NonEmptyEntity();
+ INSTANCE.setValue("foo");
+ }
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+ public EmptyEntity getEmptyEntity() {
+ return null;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnClassEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnClassEntity.java
new file mode 100644
index 0000000..55be9fc
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnClassEntity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+* @author Michal Gajdos
+*/
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+// Entity Filtering.
+@PrimaryDetailedView
+public class OneFilteringOnClassEntity {
+
+ public static final OneFilteringOnClassEntity INSTANCE;
+
+ static {
+ INSTANCE = new OneFilteringOnClassEntity();
+ INSTANCE.field = 10;
+ INSTANCE.property = "property";
+ INSTANCE.defaultEntities = Collections.singletonList(DefaultFilteringSubEntity.INSTANCE);
+ INSTANCE.subEntities = Collections.singletonList(OneFilteringSubEntity.INSTANCE);
+ INSTANCE.filtered = FilteredClassEntity.INSTANCE;
+ }
+
+ @XmlElement
+ public int field;
+ private String property;
+
+ private List<DefaultFilteringSubEntity> defaultEntities;
+ private List<OneFilteringSubEntity> subEntities;
+
+ private FilteredClassEntity filtered;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ public List<DefaultFilteringSubEntity> getDefaultEntities() {
+ return defaultEntities;
+ }
+
+ public void setDefaultEntities(final List<DefaultFilteringSubEntity> defaultEntities) {
+ this.defaultEntities = defaultEntities;
+ }
+
+ public List<OneFilteringSubEntity> getSubEntities() {
+ return subEntities;
+ }
+
+ public void setSubEntities(final List<OneFilteringSubEntity> subEntities) {
+ this.subEntities = subEntities;
+ }
+
+ public String getAccessor() {
+ return accessorTransient == null ? property + property : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+
+ public FilteredClassEntity getFiltered() {
+ return filtered;
+ }
+
+ public void setFiltered(final FilteredClassEntity filtered) {
+ this.filtered = filtered;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnPropertiesEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnPropertiesEntity.java
new file mode 100644
index 0000000..43809e4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringOnPropertiesEntity.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+* @author Michal Gajdos
+*/
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class OneFilteringOnPropertiesEntity {
+
+ public static final OneFilteringOnPropertiesEntity INSTANCE;
+
+ static {
+ INSTANCE = new OneFilteringOnPropertiesEntity();
+ INSTANCE.field = 80;
+ INSTANCE.property = "property";
+ INSTANCE.defaultEntities = Collections.singletonList(DefaultFilteringSubEntity.INSTANCE);
+ INSTANCE.subEntities = Collections.singletonList(OneFilteringSubEntity.INSTANCE);
+ INSTANCE.filtered = FilteredClassEntity.INSTANCE;
+ }
+
+ @XmlElement
+ public int field;
+ private String property;
+
+ private List<DefaultFilteringSubEntity> defaultEntities;
+
+ @PrimaryDetailedView
+ private List<OneFilteringSubEntity> subEntities;
+
+ @PrimaryDetailedView
+ private FilteredClassEntity filtered;
+
+ @XmlTransient
+ @JsonIgnore
+ public String accessorTransient;
+
+ @PrimaryDetailedView
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(final String property) {
+ this.property = property;
+ }
+
+ @PrimaryDetailedView
+ public List<DefaultFilteringSubEntity> getDefaultEntities() {
+ return defaultEntities;
+ }
+
+ public void setDefaultEntities(final List<DefaultFilteringSubEntity> defaultEntities) {
+ this.defaultEntities = defaultEntities;
+ }
+
+ public List<OneFilteringSubEntity> getSubEntities() {
+ return subEntities;
+ }
+
+ public void setSubEntities(final List<OneFilteringSubEntity> subEntities) {
+ this.subEntities = subEntities;
+ }
+
+ @PrimaryDetailedView
+ public String getAccessor() {
+ return accessorTransient == null ? property + property : accessorTransient;
+ }
+
+ public void setAccessor(final String accessor) {
+ accessorTransient = accessor;
+ }
+
+ public FilteredClassEntity getFiltered() {
+ return filtered;
+ }
+
+ public void setFiltered(final FilteredClassEntity filtered) {
+ this.filtered = filtered;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringSubEntity.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringSubEntity.java
new file mode 100644
index 0000000..149ca05
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/domain/OneFilteringSubEntity.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.domain;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+
+/**
+* @author Michal Gajdos
+*/
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class OneFilteringSubEntity {
+
+ public static final OneFilteringSubEntity INSTANCE;
+
+ static {
+ INSTANCE = new OneFilteringSubEntity();
+ INSTANCE.field1 = 20;
+ INSTANCE.field2 = 30;
+ INSTANCE.property1 = "property1";
+ INSTANCE.property2 = "property2";
+ }
+
+ @XmlElement
+ public int field1;
+
+ @XmlElement
+ @PrimaryDetailedView
+ public int field2;
+
+ private String property1;
+ private String property2;
+
+ @PrimaryDetailedView
+ public String getProperty1() {
+ return property1;
+ }
+
+ public void setProperty1(final String property1) {
+ this.property1 = property1;
+ }
+
+ public String getProperty2() {
+ return property2;
+ }
+
+ @PrimaryDetailedView
+ public void setProperty2(final String property2) {
+ this.property2 = property2;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEmptyEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEmptyEntityTest.java
new file mode 100644
index 0000000..b2ee42c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEmptyEntityTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.ext.ContextResolver;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.EmptyEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.NonEmptyEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+/**
+ * Use-cases to check whether empty class causes problems (JERSEY-2824 reproducer).
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonEmptyEntityTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ @Path("/")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class Resource {
+
+ @Path("nonEmptyEntity")
+ @GET
+ public NonEmptyEntity nonEmptyEntity() {
+ return NonEmptyEntity.INSTANCE;
+ }
+
+ @Path("emptyEntity")
+ @GET
+ public EmptyEntity emptyEntity() {
+ return new EmptyEntity();
+ }
+ }
+
+ public JsonEmptyEntityTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class)
+ .register(filteringProvider)
+ .register(new ContextResolver<ObjectMapper>() {
+ @Override
+ public ObjectMapper getContext(final Class<?> type) {
+ return new ObjectMapper()
+ .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+ }));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testNonEmptyEntity() throws Exception {
+ final NonEmptyEntity entity = target("nonEmptyEntity").request().get(NonEmptyEntity.class);
+
+ assertThat(entity.getValue(), is("foo"));
+ assertThat(entity.getEmptyEntity(), nullValue());
+ }
+
+ @Test
+ public void testEmptyEntity() throws Exception {
+ assertThat(target("emptyEntity").request().get(String.class), is("{}"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringClientTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringClientTest.java
new file mode 100644
index 0000000..9180c2e
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringClientTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.DefaultFilteringScope;
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.DefaultFilteringSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.FilteredClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringSubEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonEntityFilteringClientTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ @Parameterized.Parameter
+ public Class<Feature> filteringProvider;
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ // Resources.
+ .register(Resource.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(EntityFilteringFeature.class).register(filteringProvider);
+ }
+
+ @Path("/")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class Resource {
+
+ @POST
+ public String post(final String value) {
+ return value;
+ }
+ }
+
+ @Test
+ public void testEntityAnnotationsPrimaryView() throws Exception {
+ final OneFilteringOnClassEntity entity = target()
+ .request()
+ .post(Entity.entity(
+ OneFilteringOnClassEntity.INSTANCE,
+ MediaType.APPLICATION_JSON_TYPE,
+ new Annotation[] {PrimaryDetailedView.Factory.get()}),
+ OneFilteringOnClassEntity.class);
+
+ _testPrimaryViewEntity(entity);
+ }
+
+ @Test
+ public void testEntityAnnotationsDefaultView() throws Exception {
+ final OneFilteringOnClassEntity entity = target()
+ .request()
+ .post(Entity.entity(
+ OneFilteringOnClassEntity.INSTANCE,
+ MediaType.APPLICATION_JSON_TYPE,
+ new Annotation[] {new DefaultFilteringScope()}),
+ OneFilteringOnClassEntity.class);
+
+ _testEmptyEntity(entity);
+ }
+
+ @Test
+ public void testEntityAnnotationsInvalidView() throws Exception {
+ final OneFilteringOnClassEntity entity = target()
+ .request()
+ .post(Entity.entity(
+ OneFilteringOnClassEntity.INSTANCE,
+ MediaType.APPLICATION_JSON_TYPE,
+ new Annotation[] {CustomAnnotationLiteral.INSTANCE}),
+ OneFilteringOnClassEntity.class);
+
+ _testEmptyEntity(entity);
+ }
+
+ @Test
+ public void testConfigurationPrimaryView() throws Exception {
+ _testPrimaryViewEntity(retrieveEntity(PrimaryDetailedView.Factory.get()));
+ }
+
+ @Test
+ public void testConfigurationDefaultView() throws Exception {
+ _testEmptyEntity(retrieveEntity(new DefaultFilteringScope()));
+ }
+
+ @Test
+ public void testConfigurationMultipleViews() throws Exception {
+ _testPrimaryViewEntity(retrieveEntity(PrimaryDetailedView.Factory.get(), CustomAnnotationLiteral.INSTANCE));
+ }
+
+ private OneFilteringOnClassEntity retrieveEntity(final Annotation... annotations) {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, annotations.length == 1 ? annotations[0] : annotations);
+ configureClient(config);
+
+ return ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(OneFilteringOnClassEntity.INSTANCE, MediaType.APPLICATION_JSON_TYPE),
+ OneFilteringOnClassEntity.class);
+ }
+
+ @Test
+ public void testInvalidConfiguration() throws Exception {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, "invalid_value");
+ configureClient(config);
+
+ final OneFilteringOnClassEntity entity =
+ ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(OneFilteringOnClassEntity.INSTANCE, MediaType.APPLICATION_JSON_TYPE),
+ OneFilteringOnClassEntity.class);
+
+ _testEmptyEntity(entity);
+ }
+
+ @Test
+ public void testEntityAnnotationsOverConfiguration() throws Exception {
+ final ClientConfig config = new ClientConfig()
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, SecondaryDetailedView.Factory.get());
+ configureClient(config);
+
+ final ManyFilteringsOnClassEntity entity = ClientBuilder.newClient(config)
+ .target(getBaseUri())
+ .request()
+ .post(Entity.entity(
+ ManyFilteringsOnClassEntity.INSTANCE,
+ MediaType.APPLICATION_JSON_TYPE,
+ new Annotation[] {PrimaryDetailedView.Factory.get()}),
+ ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(50));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(0));
+ assertThat(manyFilteringsSubEntity.getProperty1(), is("property1"));
+ assertThat(manyFilteringsSubEntity.getProperty2(), nullValue());
+ }
+
+ private void _testEmptyEntity(final OneFilteringOnClassEntity entity) {
+ // OneFilteringOnClassEntity
+ assertThat(entity.field, is(0));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), nullValue());
+ }
+
+ private void _testPrimaryViewEntity(final OneFilteringOnClassEntity entity) {
+ // OneFilteringOnClassEntity
+ assertThat(entity.field, is(10));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), notNullValue());
+ assertThat(entity.getDefaultEntities().size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.getDefaultEntities().get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), notNullValue());
+ assertThat(entity.getSubEntities().size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.getSubEntities().get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnClassTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnClassTest.java
new file mode 100644
index 0000000..e18eeee
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnClassTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.DefaultFilteringScope;
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.DefaultFilteringSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.FilteredClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringSubEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Use-cases with entity-filtering annotations on class, JSON output.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonEntityFilteringOnClassTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public JsonEntityFilteringOnClassTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class).register(filteringProvider));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Path("/")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class Resource {
+
+ @GET
+ @Path("OneFilteringEntity")
+ @PrimaryDetailedView
+ public OneFilteringOnClassEntity getOneFilteringEntity() {
+ return OneFilteringOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultView")
+ public OneFilteringOnClassEntity getOneFilteringEntityDefaultView() {
+ return OneFilteringOnClassEntity.INSTANCE;
+ }
+
+ @POST
+ @Path("OneFilteringEntity")
+ public String postOneFilteringEntity(final String value) {
+ return value;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultViewResponse")
+ public Response getOneFilteringEntityDefaultViewResponse() {
+ return Response.ok().entity(OneFilteringOnClassEntity.INSTANCE, new Annotation[] {new DefaultFilteringScope()})
+ .build();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityPrimaryView")
+ @PrimaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityPrimaryView() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntitySecondaryView")
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntitySecondaryView() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityDefaultView")
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityDefaultView() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityManyViews")
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getManyFilteringsEntityManyViews() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClass() throws Exception {
+ final OneFilteringOnClassEntity entity = target("OneFilteringEntity").request().get(OneFilteringOnClassEntity.class);
+
+ // OneFilteringOnClassEntity
+ assertThat(entity.field, is(10));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), notNullValue());
+ assertThat(entity.getDefaultEntities().size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.getDefaultEntities().get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), notNullValue());
+ assertThat(entity.getSubEntities().size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.getSubEntities().get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClassDefaultViewResponse() throws Exception {
+ final OneFilteringOnClassEntity entity = target("OneFilteringEntityDefaultViewResponse").request()
+ .get(OneFilteringOnClassEntity.class);
+
+ // OneFilteringOnClassEntity
+ assertThat(entity.field, is(0));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), nullValue());
+ }
+
+ @Test
+ public void testOneEntityFilteringOnClassDefaultView() throws Exception {
+ final OneFilteringOnClassEntity entity = target("OneFilteringEntityDefaultView").request()
+ .get(OneFilteringOnClassEntity.class);
+
+ // OneFilteringOnClassEntity
+ assertThat(entity.field, is(0));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), nullValue());
+ }
+
+ @Test
+ public void testMultipleViewsOnClass() throws Exception {
+ testOneEntityFilteringOnClass();
+ testOneEntityFilteringOnClassDefaultView();
+ }
+
+ @Test
+ public void testManyFilteringsEntityPrimaryView() throws Exception {
+ final ManyFilteringsOnClassEntity entity = target("ManyFilteringsEntityPrimaryView").request()
+ .get(ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(50));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(0));
+ assertThat(manyFilteringsSubEntity.getProperty1(), is("property1"));
+ assertThat(manyFilteringsSubEntity.getProperty2(), nullValue());
+ }
+
+ @Test
+ public void testManyFilteringsEntitySecondaryView() throws Exception {
+ final ManyFilteringsOnClassEntity entity = target("ManyFilteringsEntitySecondaryView").request()
+ .get(ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(50));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(0));
+ assertThat(oneFilteringSubEntity.getProperty1(), nullValue());
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(70));
+ assertThat(manyFilteringsSubEntity.getProperty1(), nullValue());
+ assertThat(manyFilteringsSubEntity.getProperty2(), is("property2"));
+ }
+
+ @Test
+ public void testManyFilteringsEntityDefaultView() throws Exception {
+ final ManyFilteringsOnClassEntity entity = target("ManyFilteringsEntityDefaultView").request()
+ .get(ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(0));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, nullValue());
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, nullValue());
+ }
+
+ @Test
+ public void testManyFilteringsEntityManyViews() throws Exception {
+ final ManyFilteringsOnClassEntity entity = target("ManyFilteringsEntityManyViews").request()
+ .get(ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(50));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(70));
+ assertThat(manyFilteringsSubEntity.getProperty1(), is("property1"));
+ assertThat(manyFilteringsSubEntity.getProperty2(), is("property2"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnPropertiesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnPropertiesTest.java
new file mode 100644
index 0000000..2d107b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringOnPropertiesTest.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.DefaultFilteringScope;
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.DefaultFilteringSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.FilteredClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnPropertiesEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringOnPropertiesEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringSubEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Use-cases with entity-filtering annotations on properties, JSON output.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonEntityFilteringOnPropertiesTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public JsonEntityFilteringOnPropertiesTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class).register(filteringProvider));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Path("/")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class Resource {
+
+ @GET
+ @Path("OneFilteringEntity")
+ @PrimaryDetailedView
+ public OneFilteringOnPropertiesEntity getOneFilteringEntity() {
+ return OneFilteringOnPropertiesEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultView")
+ public OneFilteringOnPropertiesEntity getOneFilteringEntityDefaultView() {
+ return OneFilteringOnPropertiesEntity.INSTANCE;
+ }
+
+ @POST
+ @Path("OneFilteringEntity")
+ public String postOneFilteringEntity(final String value) {
+ return value;
+ }
+
+ @GET
+ @Path("OneFilteringEntityDefaultViewResponse")
+ public Response getOneFilteringEntityDefaultViewResponse() {
+ return Response.ok().entity(OneFilteringOnPropertiesEntity.INSTANCE, new Annotation[] {new DefaultFilteringScope()})
+ .build();
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityPrimaryView")
+ @PrimaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityPrimaryView() {
+ return ManyFilteringsOnPropertiesEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntitySecondaryView")
+ @SecondaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntitySecondaryView() {
+ return ManyFilteringsOnPropertiesEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityDefaultView")
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityDefaultView() {
+ return ManyFilteringsOnPropertiesEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("ManyFilteringsEntityManyViews")
+ @PrimaryDetailedView
+ @SecondaryDetailedView
+ public ManyFilteringsOnPropertiesEntity getManyFilteringsEntityManyViews() {
+ return ManyFilteringsOnPropertiesEntity.INSTANCE;
+ }
+ }
+
+ @Test
+ public void testOneEntityFilteringOnProperties() throws Exception {
+ final OneFilteringOnPropertiesEntity entity = target("OneFilteringEntity").request()
+ .get(OneFilteringOnPropertiesEntity.class);
+
+ // OneFilteringOnPropertiesEntity
+ assertThat(entity.field, is(80));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), notNullValue());
+ assertThat(entity.getDefaultEntities().size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.getDefaultEntities().get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), notNullValue());
+ assertThat(entity.getSubEntities().size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.getSubEntities().get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+ }
+
+ @Test
+ public void testOneEntityFilteringOnPropertiesDefaultViewResponse() throws Exception {
+ final OneFilteringOnPropertiesEntity entity = target("OneFilteringEntityDefaultViewResponse").request()
+ .get(OneFilteringOnPropertiesEntity.class);
+
+ // OneFilteringOnPropertiesEntity
+ assertThat(entity.field, is(80));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), nullValue());
+ }
+
+ @Test
+ public void testOneEntityFilteringOnPropertiesDefaultView() throws Exception {
+ final OneFilteringOnPropertiesEntity entity = target("OneFilteringEntityDefaultView").request()
+ .get(OneFilteringOnPropertiesEntity.class);
+
+ // OneFilteringOnPropertiesEntity
+ assertThat(entity.field, is(80));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.getFiltered();
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.getDefaultEntities(), nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.getSubEntities(), nullValue());
+ }
+
+ @Test
+ public void testMultipleViewsOnProperties() throws Exception {
+ testOneEntityFilteringOnProperties();
+ testOneEntityFilteringOnPropertiesDefaultView();
+ }
+
+ @Test
+ public void testManyFilteringsEntityPrimaryView() throws Exception {
+ final ManyFilteringsOnPropertiesEntity entity = target("ManyFilteringsEntityPrimaryView").request()
+ .get(ManyFilteringsOnPropertiesEntity.class);
+
+ // ManyFilteringsOnPropertiesEntity
+ assertThat(entity.field, is(90));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, nullValue());
+ }
+
+ @Test
+ public void testManyFilteringsEntitySecondaryView() throws Exception {
+ final ManyFilteringsOnPropertiesEntity entity = target("ManyFilteringsEntitySecondaryView").request()
+ .get(ManyFilteringsOnPropertiesEntity.class);
+
+ // ManyFilteringsOnPropertiesEntity
+ assertThat(entity.field, is(90));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(0));
+ assertThat(oneFilteringSubEntity.getProperty1(), nullValue());
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(70));
+ assertThat(manyFilteringsSubEntity.getProperty1(), nullValue());
+ assertThat(manyFilteringsSubEntity.getProperty2(), is("property2"));
+ }
+
+ @Test
+ public void testManyFilteringsEntityDefaultView() throws Exception {
+ final ManyFilteringsOnPropertiesEntity entity = target("ManyFilteringsEntityDefaultView").request()
+ .get(ManyFilteringsOnPropertiesEntity.class);
+
+ // ManyFilteringsOnPropertiesEntity
+ assertThat(entity.field, is(90));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, nullValue());
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, nullValue());
+ }
+
+ @Test
+ public void testManyFilteringsEntityManyViews() throws Exception {
+ final ManyFilteringsOnPropertiesEntity entity = target("ManyFilteringsEntityManyViews").request()
+ .get(ManyFilteringsOnPropertiesEntity.class);
+
+ // ManyFilteringsOnPropertiesEntity
+ assertThat(entity.field, is(90));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(70));
+ assertThat(manyFilteringsSubEntity.getProperty1(), is("property1"));
+ assertThat(manyFilteringsSubEntity.getProperty2(), is("property2"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringScopesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringScopesTest.java
new file mode 100644
index 0000000..4dba516
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringScopesTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ComplexEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ComplexSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ComplexSubSubEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonEntityFilteringScopesTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][]{{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public JsonEntityFilteringScopesTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class).register(filteringProvider));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Path("/")
+ @Consumes("application/json")
+ @Produces("application/json")
+ public static class Resource {
+
+ @GET
+ @PrimaryDetailedView
+ public ComplexEntity get() {
+ return ComplexEntity.INSTANCE;
+ }
+ }
+
+ /**
+ * Primary -> Default -> Primary.
+ */
+ @Test
+ public void testEntityFilteringScopes() throws Exception {
+ final ComplexEntity entity = target().request().get(ComplexEntity.class);
+
+ // ComplexEntity
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // ComplexSubEntity
+ final ComplexSubEntity subEntity = entity.field;
+ assertThat(subEntity, notNullValue());
+ assertThat(subEntity.accessorTransient, is("fieldfield"));
+ assertThat(subEntity.field, is("field"));
+
+ // ComplexSubSubEntity
+ final ComplexSubSubEntity subSubEntity = entity.field.getProperty();
+ assertThat(subSubEntity.accessorTransient, is("fieldfield"));
+ assertThat(subSubEntity.getProperty(), is("property"));
+ assertThat(subSubEntity.field, nullValue());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringServerTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringServerTest.java
new file mode 100644
index 0000000..5ae7b7f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/JsonEntityFilteringServerTest.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.entity.filtering.DefaultFilteringScope;
+import org.glassfish.jersey.tests.e2e.entity.filtering.PrimaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.SecondaryDetailedView;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.DefaultFilteringSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.FilteredClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsOnClassEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.ManyFilteringsSubEntity;
+import org.glassfish.jersey.tests.e2e.entity.filtering.domain.OneFilteringSubEntity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Suite;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ JsonEntityFilteringServerTest.ConfigurationServerTest.class,
+ JsonEntityFilteringServerTest.ConfigurationDefaultViewServerTest.class,
+ JsonEntityFilteringServerTest.AnnotationsServerTest.class,
+ JsonEntityFilteringServerTest.AnnotationsOverConfigurationServerTest.class
+})
+public class JsonEntityFilteringServerTest {
+
+ @Path("/")
+ @Produces("application/json")
+ public static class Resource {
+
+ @GET
+ @Path("configuration")
+ public ManyFilteringsOnClassEntity getConfiguration() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("configurationOverResource")
+ @SecondaryDetailedView
+ public ManyFilteringsOnClassEntity getConfigurationOverResource() {
+ return ManyFilteringsOnClassEntity.INSTANCE;
+ }
+
+ @GET
+ @Path("annotations")
+ public Response getAnnotations() {
+ return Response
+ .ok()
+ .entity(ManyFilteringsOnClassEntity.INSTANCE, new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverConfiguration")
+ public Response getAnnotationsOverConfiguration() {
+ return Response
+ .ok()
+ .entity(ManyFilteringsOnClassEntity.INSTANCE, new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverResource")
+ @SecondaryDetailedView
+ public Response getAnnotationsOverResource() {
+ return Response
+ .ok()
+ .entity(ManyFilteringsOnClassEntity.INSTANCE, new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+
+ @GET
+ @Path("annotationsOverConfigurationOverResource")
+ @SecondaryDetailedView
+ public Response getAnnotationsOverConfigurationOverResource() {
+ return Response
+ .ok()
+ .entity(ManyFilteringsOnClassEntity.INSTANCE, new Annotation[] {PrimaryDetailedView.Factory.get()})
+ .build();
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class ConfigurationServerTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public ConfigurationServerTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class)
+ .register(filteringProvider)
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, PrimaryDetailedView.Factory.get()));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+ _testEntity(target("configuration").request().get(ManyFilteringsOnClassEntity.class));
+ }
+
+ @Test
+ public void testConfigurationOverResource() throws Exception {
+ _testEntity(target("configurationOverResource").request().get(ManyFilteringsOnClassEntity.class));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class ConfigurationDefaultViewServerTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public ConfigurationDefaultViewServerTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class).register(filteringProvider));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+ final ManyFilteringsOnClassEntity entity = target("configuration").request().get(ManyFilteringsOnClassEntity.class);
+
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(0));
+ assertThat(entity.accessorTransient, nullValue());
+ assertThat(entity.getProperty(), nullValue());
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, nullValue());
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, nullValue());
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, nullValue());
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class AnnotationsServerTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public AnnotationsServerTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class).register(filteringProvider));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testAnnotations() throws Exception {
+ _testEntity(target("annotations").request().get(ManyFilteringsOnClassEntity.class));
+ }
+
+ @Test
+ public void testAnnotationsOverResource() throws Exception {
+ _testEntity(target("annotationsOverResource").request().get(ManyFilteringsOnClassEntity.class));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class AnnotationsOverConfigurationServerTest extends JerseyTest {
+
+ @Parameterized.Parameters(name = "Provider: {0}")
+ public static Iterable<Class[]> providers() {
+ return Arrays.asList(new Class[][] {{MoxyJsonFeature.class}, {JacksonFeature.class}});
+ }
+
+ public AnnotationsOverConfigurationServerTest(final Class<Feature> filteringProvider) {
+ super(new ResourceConfig(Resource.class, EntityFilteringFeature.class)
+ .register(filteringProvider)
+ .property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new DefaultFilteringScope()));
+
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Test
+ public void testAnnotationsOverConfiguration() throws Exception {
+ _testEntity(target("annotationsOverConfiguration").request().get(ManyFilteringsOnClassEntity.class));
+ }
+
+ @Test
+ public void testAnnotationsOverConfigurationOverResource() throws Exception {
+ _testEntity(target("annotationsOverConfigurationOverResource").request().get(ManyFilteringsOnClassEntity.class));
+ }
+ }
+
+ private static void _testEntity(final ManyFilteringsOnClassEntity entity) {
+ // ManyFilteringsOnClassEntity
+ assertThat(entity.field, is(50));
+ assertThat(entity.accessorTransient, is("propertyproperty"));
+ assertThat(entity.getProperty(), is("property"));
+
+ // FilteredClassEntity
+ final FilteredClassEntity filtered = entity.filtered;
+ assertThat(filtered, notNullValue());
+ assertThat(filtered.field, is(0));
+ assertThat(filtered.getProperty(), nullValue());
+
+ // DefaultFilteringSubEntity
+ assertThat(entity.defaultEntities, notNullValue());
+ assertThat(entity.defaultEntities.size(), is(1));
+ final DefaultFilteringSubEntity defaultFilteringSubEntity = entity.defaultEntities.get(0);
+ assertThat(defaultFilteringSubEntity.field, is(true));
+ assertThat(defaultFilteringSubEntity.getProperty(), is(20L));
+
+ // OneFilteringSubEntity
+ assertThat(entity.oneEntities, notNullValue());
+ assertThat(entity.oneEntities.size(), is(1));
+ final OneFilteringSubEntity oneFilteringSubEntity = entity.oneEntities.get(0);
+ assertThat(oneFilteringSubEntity.field1, is(20));
+ assertThat(oneFilteringSubEntity.field2, is(30));
+ assertThat(oneFilteringSubEntity.getProperty1(), is("property1"));
+ assertThat(oneFilteringSubEntity.getProperty2(), is("property2"));
+
+ // ManyFilteringsSubEntity
+ assertThat(entity.manyEntities, notNullValue());
+ assertThat(entity.manyEntities.size(), is(1));
+ final ManyFilteringsSubEntity manyFilteringsSubEntity = entity.manyEntities.get(0);
+ assertThat(manyFilteringsSubEntity.field1, is(60));
+ assertThat(manyFilteringsSubEntity.field2, is(0));
+ assertThat(manyFilteringsSubEntity.getProperty1(), is("property1"));
+ assertThat(manyFilteringsSubEntity.getProperty2(), nullValue());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/MoxyEntityFilteringTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/MoxyEntityFilteringTest.java
new file mode 100644
index 0000000..aefabf4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/json/MoxyEntityFilteringTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.entity.filtering.json;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MoxyEntityFilteringTest extends JerseyTest {
+
+ @Path("/")
+ @Produces("application/json")
+ public static class Resource {
+
+ @GET
+ public XmlElementEntity getXmlAttributeEntity() {
+ return new XmlElementEntity(new XmlAttributeEntity("foo"));
+ }
+ }
+
+ @XmlRootElement
+ public static class XmlElementEntity {
+
+ @XmlElement
+ private XmlAttributeEntity value;
+
+ public XmlElementEntity() {
+ }
+
+ private XmlElementEntity(final XmlAttributeEntity value) {
+ this.value = value;
+ }
+
+ public XmlAttributeEntity getValue() {
+ return value;
+ }
+
+ public void setValue(final XmlAttributeEntity value) {
+ this.value = value;
+ }
+ }
+
+ @XmlRootElement
+ public static class XmlAttributeEntity {
+
+ @XmlAttribute
+ private String attribute;
+
+ public XmlAttributeEntity() {
+ }
+
+ public XmlAttributeEntity(final String attribute) {
+ this.attribute = attribute;
+ }
+
+ public String getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(final String attribute) {
+ this.attribute = attribute;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(Resource.class)
+ // Features.
+ .register(EntityFilteringFeature.class);
+ }
+
+ @Test
+ public void testXmlAttributeEntity() throws Exception {
+ final XmlElementEntity entity = target().request().get(XmlElementEntity.class);
+
+ assertThat(entity, notNullValue());
+ assertThat(entity.getValue(), notNullValue());
+ assertThat(entity.getValue().getAttribute(), equalTo("foo"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/AbstractJsonTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/AbstractJsonTest.java
new file mode 100644
index 0000000..48c5afa
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/AbstractJsonTest.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.bind.JAXBContext;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.jettison.JettisonConfig;
+import org.glassfish.jersey.jettison.JettisonJaxbContext;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Common functionality for JSON tests that are using multiple JSON providers (e.g. MOXy, Jackson, Jettison).
+ *
+ * @author Michal Gajdos
+ */
+public abstract class AbstractJsonTest extends JerseyTest {
+
+ private static final String PKG_NAME = "org/glassfish/jersey/tests/e2e/json/entity/";
+ private static final Logger LOGGER = Logger.getLogger(AbstractJsonTest.class.getName());
+
+ /**
+ * Helper class representing configuration for one test case.
+ */
+ protected static final class JsonTestSetup {
+
+ private final JsonTestProvider jsonProvider;
+ private final Class<?>[] testClasses;
+
+ protected JsonTestSetup(final Class<?> testClass, final JsonTestProvider jsonProvider) {
+ this(new Class<?>[] {testClass}, jsonProvider);
+ }
+
+ protected JsonTestSetup(final Class<?>[] testClasses, final JsonTestProvider jsonProvider) {
+ this.testClasses = testClasses;
+ this.jsonProvider = jsonProvider;
+ }
+
+ public JsonTestProvider getJsonProvider() {
+ return jsonProvider;
+ }
+
+ public Set<Object> getProviders() {
+ return jsonProvider.getProviders();
+ }
+
+ public Class<?> getEntityClass() {
+ return testClasses[0];
+ }
+
+ public Class<?>[] getTestClasses() {
+ return testClasses;
+ }
+
+ public Object getTestEntity() throws Exception {
+ return getEntityClass().getDeclaredMethod("createTestInstance").invoke(null);
+ }
+ }
+
+ @Provider
+ private static final class JAXBContextResolver implements ContextResolver<JAXBContext> {
+
+ private final JAXBContext context;
+ private final Set<Class<?>> types;
+
+ public JAXBContextResolver(final JettisonConfig jsonConfiguration, final Class<?>[] classes,
+ final boolean forMoxyProvider) throws Exception {
+ this.types = new HashSet<>(Arrays.asList(classes));
+
+ if (jsonConfiguration != null) {
+ this.context = new JettisonJaxbContext(jsonConfiguration, classes);
+ } else {
+ this.context = forMoxyProvider
+ ? JAXBContextFactory.createContext(classes, new HashMap()) : JAXBContext.newInstance(classes);
+ }
+ }
+
+ @Override
+ public JAXBContext getContext(final Class<?> objectType) {
+ return (types.contains(objectType)) ? context : null;
+ }
+ }
+
+ private final JsonTestSetup jsonTestSetup;
+
+ /**
+ * Creates and configures a JAX-RS {@link Application} for given {@link JsonTestSetup}. The {@link Application} will
+ * contain one resource that can be accessed via {@code POST} method at {@code <jsonProviderName>/<entityClassName>} path.
+ * The resource also checks whether is the incoming JSON same as the one stored in a appropriate file.
+ *
+ * @param jsonTestSetup configuration to create a JAX-RS {@link Application} for.
+ * @return an {@link Application} instance.
+ */
+ private static Application configureJaxrsApplication(final JsonTestSetup jsonTestSetup) {
+ final Resource.Builder resourceBuilder = Resource.builder();
+
+ final String providerName = getProviderPathPart(jsonTestSetup);
+ final String testName = getEntityPathPart(jsonTestSetup);
+
+ resourceBuilder
+ .path("/" + providerName + "/" + testName)
+ .addMethod("POST")
+ .consumes(MediaType.APPLICATION_JSON_TYPE)
+ .produces(MediaType.APPLICATION_JSON_TYPE)
+ .handledBy(new Inflector<ContainerRequestContext, Response>() {
+
+ @Override
+ public Response apply(final ContainerRequestContext containerRequestContext) {
+ final ContainerRequest containerRequest = (ContainerRequest) containerRequestContext;
+
+ // Check if the JSON is the same as in the previous version.
+ containerRequest.bufferEntity();
+ try {
+ String json = JsonTestHelper.getResourceAsString(PKG_NAME,
+ providerName + "_" + testName + (moxyJaxbProvider() || runningOnJdk7AndLater() ? "_MOXy" : "")
+ + ".json").trim();
+
+ final InputStream entityStream = containerRequest.getEntityStream();
+ String retrievedJson = JsonTestHelper.getEntityAsString(entityStream).trim();
+ entityStream.reset();
+
+ // JAXB-RI and MOXy generate namespace prefixes differently - unify them (ns1/ns2 into ns0)
+ if (jsonTestSetup.getJsonProvider() instanceof JsonTestProvider.JettisonBadgerfishJsonTestProvider) {
+ if (retrievedJson.contains("\"ns1\"")) {
+ json = json.replace("ns1", "ns0");
+ retrievedJson = retrievedJson.replace("ns1", "ns0");
+ } else if (retrievedJson.contains("\"ns2\"")) {
+ json = json.replace("ns2", "ns0");
+ retrievedJson = retrievedJson.replace("ns2", "ns0");
+ }
+ }
+
+ if (!json.equals(retrievedJson)) {
+ LOGGER.log(Level.SEVERE, "Expected: " + json);
+ LOGGER.log(Level.SEVERE, "Actual: " + retrievedJson);
+
+ return Response.ok("{\"error\":\"JSON values doesn't match.\"}").build();
+ }
+ } catch (final IOException e) {
+ return Response.ok("{\"error\":\"Cannot find original JSON file.\"}").build();
+ }
+
+ final Object testBean = containerRequest.readEntity(jsonTestSetup.getEntityClass());
+ return Response.ok(testBean).build();
+ }
+
+ });
+
+ final ResourceConfig resourceConfig = new ResourceConfig()
+ .registerResources(resourceBuilder.build())
+ .register(jsonTestSetup.getJsonProvider().getFeature());
+
+ resourceConfig.registerInstances(getJaxbContextResolver(jsonTestSetup));
+
+ if (jsonTestSetup.getProviders() != null) {
+ resourceConfig.registerInstances(jsonTestSetup.getProviders());
+ }
+
+ return resourceConfig;
+ }
+
+ private static JAXBContextResolver getJaxbContextResolver(final JsonTestSetup jsonTestSetup) {
+ try {
+ return createJaxbContextResolver(jsonTestSetup.getJsonProvider(), jsonTestSetup.getTestClasses());
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static boolean runningOnJdk7AndLater() {
+ final String javaVersion = AccessController.doPrivileged(PropertiesHelper.getSystemProperty("java.version"));
+ final int version = Integer.valueOf(javaVersion.split("\\.")[1]);
+
+ return version >= 7;
+ }
+
+ private static boolean moxyJaxbProvider() {
+ return "org.eclipse.persistence.jaxb.JAXBContextFactory".equals(
+ AccessController.doPrivileged(PropertiesHelper.getSystemProperty("javax.xml.bind.JAXBContext")));
+ }
+
+ /**
+ * Returns entity path part for given {@link JsonTestSetup} (based on the name of the entity).
+ *
+ * @return entity path part.
+ */
+ protected static String getEntityPathPart(final JsonTestSetup jsonTestSetup) {
+ return jsonTestSetup.getEntityClass().getSimpleName();
+ }
+
+ /**
+ * Creates new {@link ContextResolver} of {@link JAXBContext} instance for given {@link JsonTestProvider} and an entity
+ * class.
+ *
+ * @param jsonProvider provider to create a context resolver for.
+ * @param clazz JAXB element class for JAXB context.
+ * @return an instance of JAXB context resolver.
+ * @throws Exception if the creation of {@code JAXBContextResolver} fails.
+ */
+ protected static JAXBContextResolver createJaxbContextResolver(final JsonTestProvider jsonProvider,
+ final Class<?> clazz) throws Exception {
+ return createJaxbContextResolver(jsonProvider, new Class<?>[] {clazz});
+ }
+
+ /**
+ * Creates new {@link ContextResolver} of {@link JAXBContext} instance for given {@link JsonTestProvider} and an entity
+ * classes.
+ *
+ * @param jsonProvider provider to create a context resolver for.
+ * @param classes JAXB element classes for JAXB context.
+ * @return an instance of JAXB context resolver.
+ * @throws Exception if the creation of {@code JAXBContextResolver} fails.
+ */
+ protected static JAXBContextResolver createJaxbContextResolver(final JsonTestProvider jsonProvider, final Class<?>[] classes)
+ throws Exception {
+ return new JAXBContextResolver(jsonProvider.getConfiguration(), classes,
+ jsonProvider instanceof JsonTestProvider.MoxyJsonTestProvider);
+ }
+
+ protected AbstractJsonTest(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(configureJaxrsApplication(jsonTestSetup));
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ this.jsonTestSetup = jsonTestSetup;
+ }
+
+ /**
+ * Returns entity path part for current test case (based on the name of the entity).
+ *
+ * @return entity path part.
+ */
+ protected String getEntityPathPart() {
+ return getEntityPathPart(jsonTestSetup);
+ }
+
+ /**
+ * Returns provider path part for current test case (based on the name of the {@link JsonTestProvider}).
+ *
+ * @return provider path part.
+ */
+ protected String getProviderPathPart() {
+ return getProviderPathPart(jsonTestSetup);
+ }
+
+ /**
+ * Returns provider path part for given {@link JsonTestSetup} (based on the name of the {@link JsonTestProvider}).
+ *
+ * @return provider path part.
+ */
+ protected static String getProviderPathPart(final JsonTestSetup jsonTestSetup) {
+ return jsonTestSetup.jsonProvider.getClass().getSimpleName();
+ }
+
+ protected JsonTestSetup getJsonTestSetup() {
+ return jsonTestSetup;
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(getJsonTestSetup().getJsonProvider().getFeature());
+
+ config.register(getJaxbContextResolver(jsonTestSetup));
+
+ // Register additional providers.
+ if (getJsonTestSetup().getProviders() != null) {
+ for (final Object provider : getJsonTestSetup().getProviders()) {
+ config.register(provider);
+ }
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ final Object entity = getJsonTestSetup().getTestEntity();
+
+ final Object receivedEntity = target()
+ .path(getProviderPathPart())
+ .path(getEntityPathPart())
+ .request("application/json; charset=UTF-8")
+ .post(Entity.entity(entity, "application/json; charset=UTF-8"), getJsonTestSetup().getEntityClass());
+
+ // Print out configuration for this test case as there is no way to rename generated JUnit tests at the moment.
+ // TODO remove once JUnit supports parameterized tests with custom names
+ // TODO (see http://stackoverflow.com/questions/650894/change-test-name-of-parameterized-tests
+ // TODO or https://github.com/KentBeck/junit/pull/393)
+ assertEquals(String.format("%s - %s: Received JSON entity content does not match expected JSON entity content.",
+ getJsonTestSetup().getJsonProvider().getClass().getSimpleName(),
+ getJsonTestSetup().getEntityClass().getSimpleName()), entity, receivedEntity);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/GenericTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/GenericTest.java
new file mode 100644
index 0000000..5f7f5b9
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/GenericTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.tests.e2e.json.entity.ColorHolder;
+import org.glassfish.jersey.tests.e2e.json.entity.Jersey1199List;
+
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Unignore when you need to run a specific test.
+ *
+ * @author Michal Gajdos
+ */
+@Ignore("Unignore only when you need to run a specific test.")
+@RunWith(Parameterized.class)
+public class GenericTest extends AbstractJsonTest {
+
+ @Parameterized.Parameters()
+ public static Collection<JsonTestSetup[]> generateTestCases() throws Exception {
+ final List<JsonTestSetup[]> jsonTestSetups = new LinkedList<JsonTestSetup[]>();
+ final Class<?>[] classes = {Jersey1199List.class, ColorHolder.class};
+
+ for (JsonTestProvider jsonProvider : new JsonTestProvider[]{new JsonTestProvider.MoxyJsonTestProvider()}) {
+ jsonTestSetups.add(new JsonTestSetup[]{new JsonTestSetup(classes, jsonProvider)});
+ }
+
+ return jsonTestSetups;
+ }
+
+ public GenericTest(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/InheritanceTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/InheritanceTest.java
new file mode 100644
index 0000000..881d15d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/InheritanceTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.tests.e2e.json.entity.Animal;
+import org.glassfish.jersey.tests.e2e.json.entity.AnimalList;
+import org.glassfish.jersey.tests.e2e.json.entity.Cat;
+import org.glassfish.jersey.tests.e2e.json.entity.Dog;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class InheritanceTest extends AbstractJsonTest {
+
+ @Parameterized.Parameters()
+ public static Collection<JsonTestSetup[]> generateTestCases() throws Exception {
+ final List<JsonTestSetup[]> jsonTestSetups = new LinkedList<JsonTestSetup[]>();
+ final Class<?>[] classes = {AnimalList.class, Animal.class, Dog.class, Cat.class};
+
+ for (final JsonTestProvider jsonProvider : JsonTestProvider.JAXB_PROVIDERS) {
+ // TODO - remove the condition after jsonb polymorphic adapter is implemented
+ if (!(jsonProvider instanceof JsonTestProvider.JsonbTestProvider)) {
+ jsonTestSetups.add(new JsonTestSetup[]{new JsonTestSetup(classes, jsonProvider)});
+ }
+ }
+
+ return jsonTestSetups;
+ }
+
+ public InheritanceTest(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jackson1JsonViewTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jackson1JsonViewTest.java
new file mode 100644
index 0000000..d71dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jackson1JsonViewTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson1.Jackson1Feature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.codehaus.jackson.map.annotate.JsonView;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer for JERSEY-1878.
+ *
+ * @author Michal Gajdos
+ */
+public class Jackson1JsonViewTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class, Jackson1Feature.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(Jackson1Feature.class);
+ }
+
+ public static class SimpleView {}
+ public static class DetailedView {}
+
+ public static class TestEntity {
+
+ public static final TestEntity ENTITY = new TestEntity("simple", "detailed");
+ public static final TestEntity DETAILED = new TestEntity(null, "detailed");
+
+ private String simple;
+ private String detailed;
+
+ public TestEntity() {
+ }
+
+ public TestEntity(final String simple, final String detailed) {
+ this.simple = simple;
+ this.detailed = detailed;
+ }
+
+ @JsonView(SimpleView.class)
+ public String getSimple() {
+ return simple;
+ }
+
+ @JsonView(DetailedView.class)
+ public String getDetailed() {
+ return detailed;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final TestEntity that = (TestEntity) o;
+
+ if (detailed != null ? !detailed.equals(that.detailed) : that.detailed != null) {
+ return false;
+ }
+ if (simple != null ? !simple.equals(that.simple) : that.simple != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = simple != null ? simple.hashCode() : 0;
+ result = 31 * result + (detailed != null ? detailed.hashCode() : 0);
+ return result;
+ }
+ }
+
+ @Path("/")
+ @Singleton
+ public static class MyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("async")
+ @JsonView(DetailedView.class)
+ public void getAsync(@Suspended final AsyncResponse response) {
+ response.resume(TestEntity.ENTITY);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("sync")
+ @JsonView(DetailedView.class)
+ public TestEntity getSync() {
+ return TestEntity.ENTITY;
+ }
+ }
+
+ @Test
+ public void testSync() throws Exception {
+ final Response response = target().path("sync").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(TestEntity.class), is(TestEntity.DETAILED));
+ }
+
+ @Test
+ public void testAsync() throws Exception {
+ final Response response = target().path("async").request().async().get().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(TestEntity.class), is(TestEntity.DETAILED));
+
+ response.close();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JacksonJsonViewTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JacksonJsonViewTest.java
new file mode 100644
index 0000000..c4c8dd9
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JacksonJsonViewTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.fasterxml.jackson.annotation.JsonView;
+
+/**
+ * Reproducer for JERSEY-1878.
+ *
+ * @author Michal Gajdos
+ */
+public class JacksonJsonViewTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class, JacksonFeature.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(JacksonFeature.class);
+ }
+
+ public static class SimpleView {}
+ public static class DetailedView {}
+
+ public static class TestEntity {
+
+ public static final TestEntity ENTITY = new TestEntity("simple", "detailed");
+ public static final TestEntity DETAILED = new TestEntity(null, "detailed");
+
+ private String simple;
+ private String detailed;
+
+ public TestEntity() {
+ }
+
+ public TestEntity(final String simple, final String detailed) {
+ this.simple = simple;
+ this.detailed = detailed;
+ }
+
+ @JsonView(SimpleView.class)
+ public String getSimple() {
+ return simple;
+ }
+
+ @JsonView(DetailedView.class)
+ public String getDetailed() {
+ return detailed;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final TestEntity that = (TestEntity) o;
+
+ if (detailed != null ? !detailed.equals(that.detailed) : that.detailed != null) {
+ return false;
+ }
+ if (simple != null ? !simple.equals(that.simple) : that.simple != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = simple != null ? simple.hashCode() : 0;
+ result = 31 * result + (detailed != null ? detailed.hashCode() : 0);
+ return result;
+ }
+ }
+
+ @Path("/")
+ @Singleton
+ public static class MyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("async")
+ @JsonView(DetailedView.class)
+ public void getAsync(@Suspended final AsyncResponse response) {
+ response.resume(TestEntity.ENTITY);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("sync")
+ @JsonView(DetailedView.class)
+ public TestEntity getSync() {
+ return TestEntity.ENTITY;
+ }
+ }
+
+ @Test
+ public void testSync() throws Exception {
+ final Response response = target().path("sync").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(TestEntity.class), is(TestEntity.DETAILED));
+ }
+
+ @Test
+ public void testAsync() throws Exception {
+ final Response response = target().path("async").request().async().get().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(TestEntity.class), is(TestEntity.DETAILED));
+
+ response.close();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JaxbTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JaxbTest.java
new file mode 100644
index 0000000..a1500d9
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JaxbTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.tests.e2e.json.entity.AnotherArrayTestBean;
+import org.glassfish.jersey.tests.e2e.json.entity.AttrAndCharDataBean;
+import org.glassfish.jersey.tests.e2e.json.entity.ComplexBeanWithAttributes;
+import org.glassfish.jersey.tests.e2e.json.entity.ComplexBeanWithAttributes2;
+import org.glassfish.jersey.tests.e2e.json.entity.ComplexBeanWithAttributes3;
+import org.glassfish.jersey.tests.e2e.json.entity.ComplexBeanWithAttributes4;
+import org.glassfish.jersey.tests.e2e.json.entity.EmptyElementBean;
+import org.glassfish.jersey.tests.e2e.json.entity.EmptyElementContainingBean;
+import org.glassfish.jersey.tests.e2e.json.entity.EncodedContentBean;
+import org.glassfish.jersey.tests.e2e.json.entity.FakeArrayBean;
+import org.glassfish.jersey.tests.e2e.json.entity.IntArray;
+import org.glassfish.jersey.tests.e2e.json.entity.ListAndNonListBean;
+import org.glassfish.jersey.tests.e2e.json.entity.ListEmptyBean;
+import org.glassfish.jersey.tests.e2e.json.entity.ListWrapperBean;
+import org.glassfish.jersey.tests.e2e.json.entity.MyResponse;
+import org.glassfish.jersey.tests.e2e.json.entity.NamespaceBean;
+import org.glassfish.jersey.tests.e2e.json.entity.NamespaceBeanWithAttribute;
+import org.glassfish.jersey.tests.e2e.json.entity.NullStringBean;
+import org.glassfish.jersey.tests.e2e.json.entity.Person;
+import org.glassfish.jersey.tests.e2e.json.entity.PureCharDataBean;
+import org.glassfish.jersey.tests.e2e.json.entity.RegisterMessage;
+import org.glassfish.jersey.tests.e2e.json.entity.SimpleBean;
+import org.glassfish.jersey.tests.e2e.json.entity.SimpleBeanWithAttributes;
+import org.glassfish.jersey.tests.e2e.json.entity.SimpleBeanWithJustOneAttribute;
+import org.glassfish.jersey.tests.e2e.json.entity.SimpleBeanWithJustOneAttributeAndValue;
+import org.glassfish.jersey.tests.e2e.json.entity.TreeModel;
+import org.glassfish.jersey.tests.e2e.json.entity.TwoListsWrapperBean;
+import org.glassfish.jersey.tests.e2e.json.entity.User;
+import org.glassfish.jersey.tests.e2e.json.entity.UserTable;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JaxbTest extends AbstractJsonTest {
+
+ private static final Class<?>[] CLASSES = {
+ AnotherArrayTestBean.class,
+ AttrAndCharDataBean.class,
+ ComplexBeanWithAttributes.class,
+ ComplexBeanWithAttributes2.class,
+ ComplexBeanWithAttributes3.class,
+ ComplexBeanWithAttributes4.class,
+ EmptyElementBean.class,
+ EmptyElementContainingBean.class,
+ EncodedContentBean.class,
+ FakeArrayBean.class,
+ IntArray.class,
+ ListAndNonListBean.class,
+ ListEmptyBean.class,
+ ListWrapperBean.class,
+ MyResponse.class,
+ NamespaceBean.class,
+ NamespaceBeanWithAttribute.class,
+ NullStringBean.class,
+ Person.class,
+ PureCharDataBean.class,
+ RegisterMessage.class,
+ SimpleBean.class,
+ SimpleBeanWithAttributes.class,
+ SimpleBeanWithJustOneAttribute.class,
+ SimpleBeanWithJustOneAttributeAndValue.class,
+ TreeModel.class,
+ TwoListsWrapperBean.class,
+ User.class,
+ UserTable.class
+ };
+
+ public JaxbTest(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+
+ @Parameterized.Parameters()
+ public static Collection<JsonTestSetup[]> getJsonProviders() throws Exception {
+ final List<JsonTestSetup[]> jsonTestSetups = new LinkedList<>();
+
+ for (final JsonTestProvider jsonProvider : JsonTestProvider.JAXB_PROVIDERS) {
+ for (final Class<?> entityClass : CLASSES) {
+ // TODO - remove the condition after jsonb polymorphic adapter is implemented
+ if (!(jsonProvider instanceof JsonTestProvider.JsonbTestProvider)) {
+ jsonTestSetups.add(new JsonTestSetup[]{new JsonTestSetup(entityClass, jsonProvider)});
+ }
+ }
+ }
+
+ return jsonTestSetups;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1199Test.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1199Test.java
new file mode 100644
index 0000000..b3dec8d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1199Test.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.json.bind.adapter.JsonbAdapter;
+
+import org.glassfish.jersey.tests.e2e.json.entity.ColorHolder;
+import org.glassfish.jersey.tests.e2e.json.entity.Jersey1199List;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class Jersey1199Test extends AbstractJsonTest {
+
+ @Parameterized.Parameters()
+ public static Collection<JsonTestSetup[]> generateTestCases() throws Exception {
+ final List<JsonTestSetup[]> jsonTestSetups = new LinkedList<>();
+ final Class<?>[] classes = {Jersey1199List.class, ColorHolder.class};
+
+ for (final JsonTestProvider jsonProvider : JsonTestProvider.JAXB_PROVIDERS) {
+ jsonTestSetups.add(new JsonTestSetup[]{new JsonTestSetup(classes, jsonProvider)});
+ }
+
+ return jsonTestSetups;
+ }
+
+ public Jersey1199Test(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+
+ /**
+ * Custom {@link JsonbAdapter} to provide JSONB with the type hidden behind the generic Object array returned by
+ * {@link Jersey1199List#getObjects()}
+ */
+ public static class JsonbObjectToColorHolderAdapter implements JsonbAdapter<Object[], ColorHolder[]> {
+
+ @Override
+ public ColorHolder[] adaptToJson(Object[] o) throws Exception {
+ return Arrays.copyOf(o, o.length, ColorHolder[].class);
+ }
+
+ @Override
+ public Object[] adaptFromJson(ColorHolder[] colorHolder) throws Exception {
+ return colorHolder;
+ }
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1835Test.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1835Test.java
new file mode 100644
index 0000000..c472aa6
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/Jersey1835Test.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.tests.e2e.json.entity.SingleItemListWrapperBean;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Reproducible test case for JERSEY-1835.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class Jersey1835Test extends AbstractJsonTest {
+
+ @Parameterized.Parameters()
+ public static Collection<JsonTestSetup[]> generateTestCases() throws Exception {
+ final List<JsonTestSetup[]> result = new LinkedList<JsonTestSetup[]>();
+ result.add(new JsonTestSetup[] {new JsonTestSetup(new Class<?>[] {SingleItemListWrapperBean.class},
+ new JsonTestProvider.JettisonMappedJsonTestProvider())});
+ return result;
+ }
+
+ public Jersey1835Test(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingDisabledTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingDisabledTest.java
new file mode 100644
index 0000000..57a4e66
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingDisabledTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.io.StringReader;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+import org.glassfish.jersey.internal.InternalProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JsonProcessingDisabledTest extends JerseyTest {
+
+ private static final String JSON_OBJECT_STR = "{\"foo\":\"bar\"}";
+ private static final JsonObject JSON_OBJECT = Json.createReader(new StringReader(JSON_OBJECT_STR)).readObject();
+
+ @Path("/")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public static class Resource {
+
+ @POST
+ @Path("jsonObject")
+ public JsonObject postJsonObject(final JsonObject jsonObject) {
+ return jsonObject;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(Resource.class)
+ .property(ServerProperties.JSON_PROCESSING_FEATURE_DISABLE, true)
+ // Make sure other JSON providers are disabled as well.
+ .property(InternalProperties.JSON_FEATURE_SERVER, "JsonProcessing");
+ }
+
+ @Test
+ public void testJsonObject() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(415, response.getStatus());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingTest.java
new file mode 100644
index 0000000..ab9f523
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonProcessingTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.io.StringReader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+
+import org.glassfish.jersey.jsonp.JsonProcessingFeature;
+import org.glassfish.jersey.server.JSONP;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+// @RunWith(ConcurrentRunner.class)
+public class JsonProcessingTest extends JerseyTest {
+
+ private static final String JSON_OBJECT_STR1 = "{\"foo\":\"bar\"}";
+ private static final String JSON_OBJECT_STR2 = "{\"foo\": 12345}";
+ private static final String JSON_ARRAY_STR1 = "[" + JSON_OBJECT_STR1 + "," + JSON_OBJECT_STR1 + "]";
+ private static final String JSON_ARRAY_STR2 = "[" + JSON_OBJECT_STR2 + "," + JSON_OBJECT_STR2 + "]";
+ private static final String JSON_ARRAY_VALUE_STR = "[null]";
+
+ private static final JsonObject JSON_OBJECT = Json.createReader(new StringReader(JSON_OBJECT_STR1)).readObject();
+ private static final JsonArray JSON_ARRAY = Json.createReader(new StringReader(JSON_ARRAY_STR1)).readArray();
+ private static final JsonArray JSON_ARRAY_VALUE = Json.createReader(new StringReader(JSON_ARRAY_VALUE_STR))
+ .readArray();
+
+ private static final JsonValue JSON_VALUE_BOOL = JsonValue.TRUE;
+ private static final JsonString JSON_VALUE_STRING = Json.createReader(
+ new StringReader(JSON_ARRAY_STR1)).readArray().getJsonObject(0).getJsonString("foo");
+ private static final JsonNumber JSON_VALUE_NUMBER = Json.createReader(
+ new StringReader(JSON_ARRAY_STR2)).readArray().getJsonObject(0).getJsonNumber("foo");
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ @Path("jsonObject")
+ public JsonObject postJsonObject(final JsonObject jsonObject) {
+ return jsonObject;
+ }
+
+ @POST
+ @Path("jsonStructure")
+ public JsonStructure postJsonStructure(final JsonStructure jsonStructure) {
+ return jsonStructure;
+ }
+
+ @POST
+ @Path("jsonArray")
+ public JsonArray postJsonArray(final JsonArray jsonArray) {
+ return jsonArray;
+ }
+
+ @POST
+ @Path("jsonValue")
+ public JsonValue postJsonValue(final JsonValue jsonValue) {
+ return jsonValue;
+ }
+
+ @POST
+ @Path("jsonString")
+ public JsonString postJsonString(final JsonString jsonString) {
+ return jsonString;
+ }
+
+ @POST
+ @Path("jsonNumber")
+ public JsonValue postJsonNumber(final JsonNumber jsonNumber) {
+ return jsonNumber;
+ }
+
+ @GET
+ @JSONP
+ @Path("jsonObjectWithPadding")
+ @Produces("application/javascript")
+ public JsonObject getJsonObjectWithPadding() {
+ return JSON_OBJECT;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(Resource.class)
+ // Make sure to disable auto-discovery (MOXy, BeanValidation, ...) and register ValidationFeature.
+ .property(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true)
+ .register(JsonProcessingFeature.class);
+ }
+
+ @Test
+ public void testJsonObject() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(JSON_OBJECT, response.readEntity(JsonObject.class));
+ }
+
+ @Test
+ public void testJsonObjectAsString() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_OBJECT_STR1));
+
+ assertEquals(JSON_OBJECT, response.readEntity(JsonObject.class));
+ }
+
+ @Test
+ public void testJsonObjectPlus() throws Exception {
+ final Response response = target("jsonObject").request("application/foo+json").post(Entity.json(JSON_OBJECT));
+
+ assertEquals(JSON_OBJECT, response.readEntity(JsonObject.class));
+ }
+
+ @Test
+ public void testJsonObjectAsStringPlus() throws Exception {
+ final Response response = target("jsonObject").request("application/foo+json")
+ .post(Entity.json(JSON_OBJECT_STR1));
+
+ assertEquals(JSON_OBJECT, response.readEntity(JsonObject.class));
+ }
+
+ @Test
+ public void testJsonObjectWrongTarget() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonObjectAsStringWrongTarget() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_OBJECT_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonObjectWrongEntity() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_ARRAY));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonObjectAsStringWrongEntity() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_ARRAY_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonObjectWrongMediaType() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_OCTET_STREAM).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonObjectAsStringWrongMediaType() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_OCTET_STREAM)
+ .post(Entity.json(JSON_OBJECT_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArray() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_ARRAY));
+
+ assertEquals(JSON_ARRAY, response.readEntity(JsonArray.class));
+ }
+
+ @Test
+ public void testJsonArrayAsString() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_ARRAY_STR1));
+
+ assertEquals(JSON_ARRAY, response.readEntity(JsonArray.class));
+ }
+
+ @Test
+ public void testJsonArrayPlus() throws Exception {
+ final Response response = target("jsonArray").request("application/foo+json").post(Entity.json(JSON_ARRAY));
+
+ assertEquals(JSON_ARRAY, response.readEntity(JsonArray.class));
+ }
+
+ @Test
+ public void testJsonArrayAsStringPlus() throws Exception {
+ final Response response = target("jsonArray").request("application/foo+json")
+ .post(Entity.json(JSON_ARRAY_STR1));
+
+ assertEquals(JSON_ARRAY, response.readEntity(JsonArray.class));
+ }
+
+ @Test
+ public void testJsonArrayWrongTarget() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_ARRAY));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArrayAsStringWrongTarget() throws Exception {
+ final Response response = target("jsonObject").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_ARRAY_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArrayWrongEntity() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArrayAsStringWrongEntity() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_OBJECT_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArrayWrongMediaType() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_OCTET_STREAM).post(Entity.json(JSON_ARRAY));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArraytAsStringWrongMediaType() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_OCTET_STREAM)
+ .post(Entity.json(JSON_ARRAY_STR1));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testJsonArrayValueEntity() throws Exception {
+ final Response response = target("jsonArray").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_ARRAY_VALUE));
+
+ assertEquals(JSON_ARRAY_VALUE, response.readEntity(JsonArray.class));
+ }
+
+ @Test
+ public void testJsonStructureArray() throws Exception {
+ final Response response = target("jsonStructure").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_ARRAY));
+
+ assertEquals(JSON_ARRAY, response.readEntity(JsonStructure.class));
+ }
+
+ @Test
+ public void testJsonStructureObject() throws Exception {
+ final Response response = target("jsonStructure").request(MediaType.APPLICATION_JSON).post(Entity.json(JSON_OBJECT));
+
+ assertEquals(JSON_OBJECT, response.readEntity(JsonStructure.class));
+ }
+
+ @Test
+ public void testJsonValueBool() throws Exception {
+ final Response response = target("jsonValue").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_VALUE_BOOL));
+
+ assertEquals(JSON_VALUE_BOOL, response.readEntity(JsonValue.class));
+ }
+
+ @Test
+ public void testJsonValueString() throws Exception {
+ final Response response = target("jsonString").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_VALUE_STRING));
+
+ assertEquals(JSON_VALUE_STRING, response.readEntity(JsonString.class));
+ }
+
+ @Test
+ public void testJsonValueStringAsValue() throws Exception {
+ final Response response = target("jsonValue").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_VALUE_STRING));
+
+ assertEquals(JSON_VALUE_STRING, response.readEntity(JsonString.class));
+ }
+
+ @Test
+ public void testJsonValueStringAsString() throws Exception {
+ final Response response = target("jsonValue").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json("\"Red 5\""));
+
+ assertEquals("Red 5", response.readEntity(JsonString.class).getString());
+ }
+
+ @Test
+ public void testJsonValueNumber() throws Exception {
+ final Response response = target("jsonNumber").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_VALUE_NUMBER));
+
+ assertEquals(JSON_VALUE_NUMBER, response.readEntity(JsonNumber.class));
+ }
+
+ @Test
+ public void testJsonValueNumberAsValue() throws Exception {
+ final Response response = target("jsonValue").request(MediaType.APPLICATION_JSON)
+ .post(Entity.json(JSON_VALUE_NUMBER));
+
+ assertEquals(JSON_VALUE_NUMBER, response.readEntity(JsonNumber.class));
+ }
+
+ @Test
+ public void testJsonObjectWithPadding() throws Exception {
+ final Response response = target("jsonObjectWithPadding").request("application/javascript").get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(JSONP.DEFAULT_CALLBACK + "(" + JSON_OBJECT_STR1 + ")"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestHelper.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestHelper.java
new file mode 100644
index 0000000..1706ceb
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestHelper.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+public class JsonTestHelper {
+
+ public static String getResourceAsString(String prefix, String resource) throws IOException {
+ return getEntityAsString(Thread.currentThread().getContextClassLoader().getResourceAsStream(prefix + resource));
+ }
+
+ public static String getEntityAsString(InputStream inputStream) throws IOException {
+ Reader reader = new InputStreamReader(inputStream);
+ StringBuilder sb = new StringBuilder();
+ char[] c = new char[1024];
+ int l;
+ while ((l = reader.read(c)) != -1) {
+ sb.append(c, 0, l);
+ }
+ return sb.toString();
+ }
+
+ public static <T> T createTestInstance(Class<T> clazz) {
+ try {
+ Method createMethod = clazz.getDeclaredMethod("createTestInstance");
+ //noinspection unchecked
+ return (T) createMethod.invoke(clazz);
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ public static boolean isCollectionEmpty(final Collection<?> collection) {
+ return collection == null || collection.isEmpty();
+ }
+
+ public static <T> boolean areCollectionsEqual(final Collection<T> collection1, final Collection<T> collection2) {
+ return collection1 == collection2
+ || (isCollectionEmpty(collection1) && isCollectionEmpty(collection2))
+ || (collection1 != null && collection1.equals(collection2));
+ }
+
+ public static boolean isArrayEmpty(final Object[] array) {
+ return array == null || array.length == 0;
+ }
+
+ public static <T> boolean areArraysEqual(final T[] array1, final T[] array2) {
+ return array1 == array2
+ || (isArrayEmpty(array1) && isArrayEmpty(array2))
+ || Arrays.equals(array1, array2);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestProvider.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestProvider.java
new file mode 100644
index 0000000..3c72b60
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonTestProvider.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.jackson1.Jackson1Feature;
+import org.glassfish.jersey.jettison.JettisonConfig;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.jsonb.JsonBindingFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+
+/**
+ * Common class for JSON providers that should be used for testing JSON capabilities.
+ *
+ * @author Michal Gajdos
+ */
+public abstract class JsonTestProvider {
+
+ public static final Collection<JsonTestProvider> JAXB_PROVIDERS = new LinkedHashSet<JsonTestProvider>() {{
+ add(new JacksonJsonTestProvider());
+ add(new Jackson1JsonTestProvider());
+ add(new JettisonMappedJsonTestProvider());
+ add(new JettisonBadgerfishJsonTestProvider());
+ add(new MoxyJsonTestProvider());
+ add(new JsonbTestProvider());
+ }};
+
+ // TODO add MoxyJsonTestProvider once MOXy supports POJO
+ public static final Collection<JsonTestProvider> POJO_PROVIDERS = new LinkedHashSet<JsonTestProvider>() {{
+ add(new JacksonJsonTestProvider());
+ add(new Jackson1JsonTestProvider());
+ }};
+
+ private Feature feature;
+ private JettisonConfig configuration;
+ private Set<Object> providers = new LinkedHashSet<>();
+
+ public static class JettisonMappedJsonTestProvider extends JsonTestProvider {
+
+ public JettisonMappedJsonTestProvider() {
+ final JettisonConfig jsonConfiguration =
+ JettisonConfig.mappedJettison().xml2JsonNs(new HashMap<String,
+ String>() {{
+ put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ put("http://example.com", "example");
+ put("http://test.jaxb.com", "jaxb");
+ }}).serializeAsArray("singleItemList").build();
+
+ setFeature(new JettisonFeature());
+ setConfiguration(jsonConfiguration);
+ }
+
+ }
+
+ public static class JettisonBadgerfishJsonTestProvider extends JsonTestProvider {
+
+ public JettisonBadgerfishJsonTestProvider() {
+ setFeature(new JettisonFeature());
+
+ setConfiguration(JettisonConfig.badgerFish().build());
+ }
+
+ }
+
+ public static class MoxyJsonTestProvider extends JsonTestProvider {
+
+ public MoxyJsonTestProvider() {
+ setFeature(new MoxyJsonFeature());
+ getProviders().add(new MoxyJsonConfigurationContextResolver());
+ }
+
+ }
+
+ @Provider
+ protected static final class MoxyJsonConfigurationContextResolver implements ContextResolver<MoxyJsonConfig> {
+
+ @Override
+ public MoxyJsonConfig getContext(final Class<?> objectType) {
+ final MoxyJsonConfig configuration = new MoxyJsonConfig();
+
+ final Map<String, String> namespacePrefixMapper = new HashMap<>(1);
+ namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ namespacePrefixMapper.put("http://example.com", "example");
+ namespacePrefixMapper.put("http://test.jaxb.com", "jaxb");
+
+ configuration.setNamespacePrefixMapper(namespacePrefixMapper);
+ configuration.setNamespaceSeparator(':');
+
+ return configuration;
+ }
+ }
+
+ @Provider
+ protected static final class JsonbContextResolver implements ContextResolver<Jsonb> {
+
+ @Override
+ public Jsonb getContext(Class<?> type) {
+ JsonbConfig config = new JsonbConfig();
+ return JsonbBuilder.create(config);
+ }
+ }
+
+ public static class JacksonJsonTestProvider extends JsonTestProvider {
+
+ public JacksonJsonTestProvider() {
+ setFeature(new JacksonFeature());
+ }
+
+ }
+
+ public static class Jackson1JsonTestProvider extends JsonTestProvider {
+ public Jackson1JsonTestProvider() {
+ setFeature(new Jackson1Feature());
+ }
+ }
+
+ public static class JsonbTestProvider extends JsonTestProvider {
+ public JsonbTestProvider() {
+ setFeature(new JsonBindingFeature());
+ getProviders().add(new JsonbContextResolver());
+ }
+ }
+
+ public JettisonConfig getConfiguration() {
+ return configuration;
+ }
+
+ protected void setConfiguration(final JettisonConfig configuration) {
+ this.configuration = configuration;
+ }
+
+ public Feature getFeature() {
+ return feature;
+ }
+
+ protected void setFeature(final Feature feature) {
+ this.feature = feature;
+ }
+
+ public Set<Object> getProviders() {
+ return providers;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingEncodingFilterTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingEncodingFilterTest.java
new file mode 100644
index 0000000..2d2e50c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingEncodingFilterTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.DeflateEncoder;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.JSONP;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.filter.EncodingFilter;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests, that JSONP callback wrapping takes places before the eventual entity compression.
+ *
+ * See https://java.net/jira/browse/JERSEY-2524 for the original issue description.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class JsonWithPaddingEncodingFilterTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(MyResource.class)
+ .register(JacksonFeature.class)
+ .register(EncodingFilter.class)
+ .register(GZipEncoder.class)
+ .register(DeflateEncoder.class);
+ }
+
+ @Path("rest")
+ public static class MyResource {
+ @GET
+ @Path("jsonp")
+ @JSONP(queryParam = JSONP.DEFAULT_QUERY)
+ @Produces("application/x-javascript")
+ public Message getHelloJsonP(@Context final HttpHeaders headers) {
+ final MultivaluedMap<String, String> headerParams = headers.getRequestHeaders();
+ for (final String key : headerParams.keySet()) {
+ System.out.println(key + ": ");
+ for (final String value : headerParams.get(key)) {
+ System.out.print(value + ", ");
+ }
+ System.out.println("\b\b");
+ }
+ return new Message("Hello world JsonP!", "English");
+ }
+ }
+
+ public static class Message {
+ private String greeting;
+ private String language;
+
+ public Message(final String greeting, final String language) {
+ this.greeting = greeting;
+ this.language = language;
+ }
+
+ public String getGreeting() {
+ return greeting;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+ }
+
+ @Test
+ public void testCorrectGzipDecoding() {
+ final Response response = target().path("rest/jsonp").queryParam("__callback", "dialog")
+ .register(GZipEncoder.class).request("application/x-javascript")
+ .header("Accept-Encoding", "gzip").get();
+
+ final String result = response.readEntity(String.class);
+ assertEquals("gzip", response.getHeaders().getFirst("Content-Encoding"));
+
+ assertTrue(result.startsWith("dialog("));
+ assertTrue(result.contains("Hello world JsonP!"));
+ assertTrue(result.contains("English"));
+ }
+
+ @Test
+ public void testCorrectDeflateDecoding() {
+ final Response response = target().path("rest/jsonp").queryParam("__callback", "dialog")
+ .register(DeflateEncoder.class).request("application/x-javascript")
+ .header("Accept-Encoding", "deflate").get();
+
+ final String result = response.readEntity(String.class);
+ assertEquals("deflate", response.getHeaders().getFirst("Content-Encoding"));
+
+ assertTrue(result.startsWith("dialog("));
+ assertTrue(result.contains("Hello world JsonP!"));
+ assertTrue(result.contains("English"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingTest.java
new file mode 100644
index 0000000..17f35df
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/JsonWithPaddingTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.JSONP;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class JsonWithPaddingTest extends JerseyTest {
+
+ @SuppressWarnings("UnusedDeclaration")
+ @XmlRootElement
+ public static class JsonBean {
+
+ private String attribute;
+
+ public JsonBean() {
+ }
+
+ public JsonBean(final String attr) {
+ this.attribute = attr;
+ }
+
+ public static JsonBean createTestInstance() {
+ return new JsonBean("attr");
+ }
+
+ public String getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(final String attribute) {
+ this.attribute = attribute;
+ }
+ }
+
+ @Path("jsonp")
+ @Produces({"application/x-javascript", "application/json"})
+ public static class JsonResource {
+
+ @GET
+ @Path("PureJson")
+ public JsonBean getPureJson() {
+ return JsonBean.createTestInstance();
+ }
+
+ @GET
+ @JSONP
+ @Path("JsonWithPaddingDefault")
+ public JsonBean getJsonWithPaddingDefault() {
+ return JsonBean.createTestInstance();
+ }
+
+ @GET
+ @JSONP(queryParam = "eval")
+ @Path("JsonWithPaddingQueryCallbackParam")
+ public JsonBean getJsonWithPaddingQueryCallbackParam() {
+ return JsonBean.createTestInstance();
+ }
+
+ @GET
+ @JSONP(callback = "parse", queryParam = "eval")
+ @Path("JsonWithPaddingCallbackAndQueryCallbackParam")
+ public JsonBean getJsonWithPaddingCallbackAndQueryCallbackParam() {
+ return JsonBean.createTestInstance();
+ }
+
+ @GET
+ @JSONP(callback = "eval")
+ @Path("JsonWithPaddingCallback")
+ public JsonBean getJsonWithPaddingCallback() {
+ return JsonBean.createTestInstance();
+ }
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<JsonTestProvider[]> getJsonProviders() throws Exception {
+ final List<JsonTestProvider[]> testProviders = new LinkedList<>();
+
+ for (final JsonTestProvider jsonProvider : JsonTestProvider.JAXB_PROVIDERS) {
+ testProviders.add(new JsonTestProvider[] {jsonProvider});
+ }
+
+ return testProviders;
+ }
+
+ private final JsonTestProvider jsonTestProvider;
+ private final String errorMessage;
+
+ public JsonWithPaddingTest(final JsonTestProvider jsonTestProvider) throws Exception {
+ super(configureJaxrsApplication(jsonTestProvider));
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ this.jsonTestProvider = jsonTestProvider;
+ this.errorMessage = String.format("%s: Received JSON entity content does not match expected JSON entity content.",
+ jsonTestProvider.getClass().getSimpleName());
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(jsonTestProvider.getFeature());
+ }
+
+ private static Application configureJaxrsApplication(final JsonTestProvider jsonTestProvider) {
+ final ResourceConfig resourceConfig = new ResourceConfig()
+ .registerClasses(JsonResource.class)
+ .register(jsonTestProvider.getFeature());
+
+ if (jsonTestProvider.getProviders() != null) {
+ resourceConfig.registerInstances(jsonTestProvider.getProviders());
+ }
+
+ return resourceConfig;
+ }
+
+ @Test
+ public void testJson() throws Exception {
+ final Response response = target("jsonp").path("PureJson").request("application/json").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType().toString(), equalTo("application/json"));
+
+ final String entity = response.readEntity(String.class);
+
+ assertThat(errorMessage, entity, allOf(not(startsWith("callback(")), not(endsWith(")"))));
+ }
+
+ @Test
+ public void testJsonWithJavaScriptMediaType() throws Exception {
+ final Response response = target("jsonp").path("PureJson").request("application/x-javascript").get();
+
+ // Method is invoked but we do not have a MBW for application/x-javascript.
+ if (jsonTestProvider.getFeature().getClass() == JacksonFeature.class) {
+ assertThat(response.getStatus(), equalTo(200));
+ } else {
+ assertThat(response.getStatus(), equalTo(500));
+ }
+ }
+
+ @Test
+ public void testJsonWithPaddingDefault() throws Exception {
+ test("JsonWithPaddingDefault", "callback");
+ }
+
+ @Test
+ public void testJsonWithPaddingQueryCallbackParam() throws Exception {
+ test("JsonWithPaddingQueryCallbackParam", "eval", "parse");
+ }
+
+ @Test
+ public void testJsonWithPaddingQueryCallbackParamDefaultQueryParam() throws Exception {
+ test("JsonWithPaddingQueryCallbackParam", "callback", "parse", "callback");
+ }
+
+ @Test
+ public void testJsonWithPaddingQueryCallbackParamDefaultCallback() throws Exception {
+ test("JsonWithPaddingQueryCallbackParam", null, "callback");
+ }
+
+ @Test
+ public void testJsonWithPaddingQueryCallbackParamNegative() throws Exception {
+ test("JsonWithPaddingQueryCallbackParam", "call", "parse", true);
+ }
+
+ @Test
+ public void testJsonWithPaddingCallbackAndQueryCallbackParam() throws Exception {
+ test("JsonWithPaddingCallbackAndQueryCallbackParam", "eval", "run");
+ }
+
+ @Test
+ public void testJsonWithPaddingCallbackAndQueryCallbackParamNegative() throws Exception {
+ test("JsonWithPaddingCallbackAndQueryCallbackParam", "eval", "run", "parse", true);
+ }
+
+ @Test
+ public void testJsonWithPaddingCallbackAndQueryCallbackParamDefault() throws Exception {
+ test("JsonWithPaddingCallbackAndQueryCallbackParam", "evalx", "parse");
+ }
+
+ @Test
+ public void testJsonWithPaddingCallbackAndQueryCallbackParamDefaultNegative() throws Exception {
+ test("JsonWithPaddingCallbackAndQueryCallbackParam", "evalx", "xlave", "eval", true);
+ }
+
+ @Test
+ public void testJsonWithPaddingCallback() throws Exception {
+ test("JsonWithPaddingCallback", "eval", "eval");
+ }
+
+ @Test
+ public void testJsonWithPaddingCallbackNegative() throws Exception {
+ test("JsonWithPaddingCallback", "eval", "lave", true);
+ }
+
+ private void test(final String path, final String callback) {
+ test(path, null, null, callback);
+ }
+
+ private void test(final String path, final String queryParamName, final String callback) {
+ test(path, queryParamName, callback, callback, false);
+ }
+
+ private void test(final String path, final String queryParamName, final String callback, final boolean isNegative) {
+ test(path, queryParamName, callback, callback, isNegative);
+ }
+
+ private void test(final String path, final String queryParamName, final String queryParamValue, final String callback) {
+ test(path, queryParamName, queryParamValue, callback, false);
+ }
+
+ private void test(final String path, final String queryParamName, final String queryParamValue, final String callback,
+ final boolean isNegative) {
+
+ WebTarget tempTarget = target("jsonp").path(path);
+ if (queryParamName != null) {
+ tempTarget = tempTarget.queryParam(queryParamName, queryParamValue);
+ }
+
+ final Response response = tempTarget.request("application/x-javascript").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType().toString(), equalTo("application/x-javascript"));
+
+ final String entity = response.readEntity(String.class);
+
+ // Check the entity.
+ final Matcher<String> startsWith = startsWith(callback + "(");
+ final Matcher<String> endsWith = endsWith(")");
+
+ final Matcher<String> callbackMatcher = isNegative ? not(startsWith) : startsWith;
+
+ assertThat(errorMessage, entity, allOf(callbackMatcher, endsWith));
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/PojoTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/PojoTest.java
new file mode 100644
index 0000000..26475b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/PojoTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.tests.e2e.json.entity.pojo.PojoAnimal;
+import org.glassfish.jersey.tests.e2e.json.entity.pojo.PojoAnimalList;
+import org.glassfish.jersey.tests.e2e.json.entity.pojo.PojoCat;
+import org.glassfish.jersey.tests.e2e.json.entity.pojo.PojoDog;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class PojoTest extends AbstractJsonTest {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<JsonTestSetup[]> generateTestCases() throws Exception {
+ final List<JsonTestSetup[]> jsonTestSetups = new LinkedList<>();
+ final Class<?>[] classes = {PojoAnimalList.class, PojoAnimal.class, PojoDog.class, PojoCat.class};
+
+ for (final JsonTestProvider jsonProvider : JsonTestProvider.POJO_PROVIDERS) {
+ jsonTestSetups.add(new JsonTestSetup[]{
+ new JsonTestSetup(classes, jsonProvider)
+ });
+ }
+
+ return jsonTestSetups;
+ }
+
+ public PojoTest(final JsonTestSetup jsonTestSetup) throws Exception {
+ super(jsonTestSetup);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Animal.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Animal.java
new file mode 100644
index 0000000..1073589
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Animal.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+// Jackson 1
+@org.codehaus.jackson.annotate.JsonTypeInfo(
+ use = org.codehaus.jackson.annotate.JsonTypeInfo.Id.NAME,
+ include = org.codehaus.jackson.annotate.JsonTypeInfo.As.PROPERTY)
+@org.codehaus.jackson.annotate.JsonSubTypes({
+ @org.codehaus.jackson.annotate.JsonSubTypes.Type(value = Cat.class),
+ @org.codehaus.jackson.annotate.JsonSubTypes.Type(value = Dog.class) })
+// Jackson 2
+@com.fasterxml.jackson.annotation.JsonTypeInfo(
+ use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME,
+ include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY)
+@com.fasterxml.jackson.annotation.JsonSubTypes({
+ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = Cat.class),
+ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = Dog.class) })
+//
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "animal")
+public class Animal {
+
+ public String name;
+
+ public Animal() {
+ }
+
+ public Animal(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Animal other = (Animal) obj;
+ if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"name\":\"%s\"}", name);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnimalList.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnimalList.java
new file mode 100644
index 0000000..59d7fbe
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnimalList.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "animalList")
+public class AnimalList {
+
+ public List<Animal> animals;
+
+ public static Object createTestInstance() {
+ final AnimalList aList = new AnimalList();
+ aList.animals = new LinkedList<>();
+ aList.animals.add(new Dog("Fifi"));
+ aList.animals.add(new Cat("Daisy"));
+ return aList;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AnimalList other = (AnimalList) obj;
+ if (this.animals != other.animals && (this.animals == null || !this.animals.equals(other.animals))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 89 * hash + (this.animals != null ? this.animals.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (animals != null) ? animals.toString() : null;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherAnimal.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherAnimal.java
new file mode 100644
index 0000000..a41bbfc
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherAnimal.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "animal")
+public class AnotherAnimal {
+
+ public String name;
+
+ public AnotherAnimal() {
+ }
+
+ public AnotherAnimal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AnotherAnimal other = (AnotherAnimal) obj;
+ if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"name\":\"%s\"}", name);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherArrayTestBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherArrayTestBean.java
new file mode 100644
index 0000000..6daa660
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherArrayTestBean.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbTransient;
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+@SuppressWarnings({"UnusedDeclaration", "SimplifiableIfStatement", "StringEquality"})
+@XmlRootElement()
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class AnotherArrayTestBean {
+
+ public static Object createTestInstance() {
+ AnotherArrayTestBean one = new AnotherArrayTestBean();
+ AnotherCat c1 = new AnotherCat("Foo", "Kitty");
+ one.addCat(c1);
+ AnotherCat c2 = new AnotherCat("Bar", "Puss");
+ one.addCat(c2);
+
+ one.setProp("testProp");
+
+ return one;
+ }
+
+ @XmlElement(required = true)
+ protected List<AnotherCat> cats;
+ protected String prop;
+
+ public AnotherArrayTestBean() {
+ this.cats = new ArrayList<>();
+ }
+
+ public void setCats(List<AnotherCat> cats) {
+ this.cats = cats;
+ }
+
+ @JsonbTransient
+ @XmlTransient
+ public List<AnotherCat> getTheCats() {
+ return this.cats;
+ }
+
+ public void addCat(AnotherCat c) {
+ this.cats.add(c);
+ }
+
+ public String getProp() {
+ return prop;
+ }
+
+ public void setProp(String prop) {
+ this.prop = prop;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AnotherArrayTestBean other = (AnotherArrayTestBean) obj;
+ if (this.prop != other.prop && (this.prop == null || !this.prop.equals(other.prop))) {
+ return false;
+ }
+ return JsonTestHelper.areCollectionsEqual(cats, other.cats);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 79 * hash + (this.prop != null ? this.prop.hashCode() : 0);
+ hash = 79 * hash + (this.cats != null ? this.cats.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("AATB(a=%s, cd=%s)", prop, cats).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherCat.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherCat.java
new file mode 100644
index 0000000..3d260ec
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AnotherCat.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement(name = "cat")
+public class AnotherCat extends AnotherAnimal {
+
+ private String nickName;
+
+ public AnotherCat() {
+ }
+
+ public AnotherCat(String name) {
+ super(name);
+ }
+
+ public AnotherCat(String name, String nickName) {
+ super(name);
+ this.nickName = nickName;
+ }
+
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ public String getNickName() {
+ return this.nickName;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"cat\" : %s , %s}", super.toString(), this.nickName);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AttrAndCharDataBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AttrAndCharDataBean.java
new file mode 100644
index 0000000..b39cbf4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/AttrAndCharDataBean.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement"})
+@XmlRootElement(name = "parent")
+public class AttrAndCharDataBean {
+
+ @XmlAttribute
+ public String attr;
+ @XmlValue
+ public String value;
+
+ public static Object createTestInstance() {
+ AttrAndCharDataBean instance = new AttrAndCharDataBean();
+ instance.attr = "aval";
+ instance.value = "pval";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AttrAndCharDataBean other = (AttrAndCharDataBean) obj;
+ if (this.attr != other.attr && (this.attr == null || !this.attr.equals(other.attr))) {
+ return false;
+ }
+ if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 79 * hash + (this.attr != null ? this.attr.hashCode() : 0);
+ hash = 79 * hash + (this.value != null ? this.value.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("ACD(a=%s, cd=%s)", attr, value).toString();
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Cat.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Cat.java
new file mode 100644
index 0000000..b962e8b
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Cat.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement(name = "cat")
+public class Cat extends Animal {
+
+ private String nickName;
+
+ public Cat() {
+ }
+
+ public Cat(final String name) {
+ super(name);
+ }
+
+ public Cat(final String name, final String nickName) {
+ super(name);
+ this.nickName = nickName;
+ }
+
+ public void setNickName(final String nickName) {
+ this.nickName = nickName;
+ }
+
+ public String getNickName() {
+ return this.nickName;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"cat\" : %s , %s}", super.toString(), this.nickName);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Color.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Color.java
new file mode 100644
index 0000000..79272c2
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Color.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+/**
+ * @author Michal Gajdos
+ */
+public enum Color {
+ RED,
+ GREEN,
+ BLUE
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ColorHolder.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ColorHolder.java
new file mode 100644
index 0000000..b9e5cfd
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ColorHolder.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement
+public class ColorHolder {
+
+ private Set<Color> colors;
+
+ public ColorHolder() {
+ }
+
+ public ColorHolder(final Set<Color> colors) {
+ this.colors = colors;
+ }
+
+ public Set<Color> getColors() {
+ return colors;
+ }
+
+ public void setColors(final Set<Color> colors) {
+ this.colors = colors;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof ColorHolder)) {
+ return false;
+ }
+
+ final ColorHolder other = (ColorHolder) obj;
+
+ return JsonTestHelper.areCollectionsEqual(this.colors, other.colors);
+ }
+
+ @Override
+ public int hashCode() {
+ return colors == null ? super.hashCode() : 19 * colors.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new Formatter().format("CH(%s)", colors).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes.java
new file mode 100644
index 0000000..bfbb41f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement"})
+@XmlRootElement
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class ComplexBeanWithAttributes {
+
+ @XmlAttribute
+ public String a1;
+ @XmlAttribute
+ public int a2;
+ @XmlElement
+ public String filler1;
+ @XmlElement
+ public List<SimpleBeanWithAttributes> list;
+ @XmlElement
+ public String filler2;
+ @XmlElement
+ SimpleBeanWithAttributes b;
+
+ public static Object createTestInstance() {
+ ComplexBeanWithAttributes instance = new ComplexBeanWithAttributes();
+ instance.a1 = "hello dolly";
+ instance.a2 = 31415926;
+ instance.filler1 = "111";
+ instance.filler2 = "222";
+ instance.b = JsonTestHelper.createTestInstance(SimpleBeanWithAttributes.class);
+ instance.list = new LinkedList<>();
+ instance.list.add(JsonTestHelper.createTestInstance(SimpleBeanWithAttributes.class));
+ instance.list.add(JsonTestHelper.createTestInstance(SimpleBeanWithAttributes.class));
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ComplexBeanWithAttributes)) {
+ return false;
+ }
+ final ComplexBeanWithAttributes other = (ComplexBeanWithAttributes) obj;
+ if (this.a1 != other.a1 && (this.a1 == null || !this.a1.equals(other.a1))) {
+ return false;
+ }
+ if (this.a2 != other.a2) {
+ return false;
+ }
+ if (this.b != other.b && (this.b == null || !this.b.equals(other.b))) {
+ return false;
+ }
+ if (this.filler1 != other.filler1 && (this.filler1 == null || !this.filler1.equals(other.filler1))) {
+ return false;
+ }
+ if (this.filler2 != other.filler2 && (this.filler2 == null || !this.filler2.equals(other.filler2))) {
+ return false;
+ }
+ if (this.list != other.list && (this.list == null || !this.list.equals(other.list))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.a1 != null ? this.a1.hashCode() : 0);
+ hash = 19 * hash + this.a2;
+ hash = 19 * hash + (this.b != null ? this.b.hashCode() : 0);
+ hash = 19 * hash + (this.filler1 != null ? this.filler1.hashCode() : 0);
+ hash = 19 * hash + (this.filler2 != null ? this.filler2.hashCode() : 0);
+ hash = 19 * hash + (this.list != null ? this.list.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("CBWA(%s,%d,%s)", a1, a2, b).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes2.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes2.java
new file mode 100644
index 0000000..d247ca7
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes2.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("StringEquality")
+@XmlRootElement
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class ComplexBeanWithAttributes2 {
+
+ @XmlAttribute
+ public String a1;
+ @XmlAttribute
+ public int a2;
+ @XmlElement
+ public String filler1;
+ @XmlElement
+ public List<SimpleBeanWithJustOneAttribute> list;
+ @XmlElement
+ public String filler2;
+ @XmlElement
+ SimpleBeanWithJustOneAttribute b;
+
+ public static Object createTestInstance() {
+ ComplexBeanWithAttributes2 instance = new ComplexBeanWithAttributes2();
+ instance.a1 = "hello dolly";
+ instance.a2 = 31415926;
+ instance.filler1 = "111";
+ instance.filler2 = "222";
+ instance.b = JsonTestHelper.createTestInstance(SimpleBeanWithJustOneAttribute.class);
+ instance.list = new LinkedList<SimpleBeanWithJustOneAttribute>();
+ instance.list.add(JsonTestHelper.createTestInstance(SimpleBeanWithJustOneAttribute.class));
+ instance.list.add(JsonTestHelper.createTestInstance(SimpleBeanWithJustOneAttribute.class));
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ComplexBeanWithAttributes2)) {
+ return false;
+ }
+ final ComplexBeanWithAttributes2 other = (ComplexBeanWithAttributes2) obj;
+ if (this.a1 != other.a1 && (this.a1 == null || !this.a1.equals(other.a1))) {
+ System.out.println("a1 differs");
+ return false;
+ }
+ if (this.a2 != other.a2) {
+ System.out.println("a2 differs");
+ return false;
+ }
+ if (this.b != other.b && (this.b == null || !this.b.equals(other.b))) {
+ System.out.println("b differs");
+ return false;
+ }
+ if (this.filler1 != other.filler1 && (this.filler1 == null || !this.filler1.equals(other.filler1))) {
+ System.out.println("f1 differs");
+ return false;
+ }
+ if (this.filler2 != other.filler2 && (this.filler2 == null || !this.filler2.equals(other.filler2))) {
+ System.out.println("f2 differs");
+ return false;
+ }
+ if (this.list != other.list && (this.list == null || !this.list.equals(other.list))) {
+ System.out.println("list differs");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.a1 != null ? this.a1.hashCode() : 0);
+ hash = 19 * hash + this.a2;
+ hash = 19 * hash + (this.b != null ? this.b.hashCode() : 0);
+ hash = 19 * hash + (this.filler1 != null ? this.filler1.hashCode() : 0);
+ hash = 19 * hash + (this.filler2 != null ? this.filler2.hashCode() : 0);
+ hash = 19 * hash + (this.list != null ? this.list.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CBWA2(%s,%d,%s,%s)", a1, a2, b, listAsString());
+ }
+
+ private String listAsString() {
+ return (list != null) ? list.toString() : null;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes3.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes3.java
new file mode 100644
index 0000000..a7b6774
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes3.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@XmlRootElement
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class ComplexBeanWithAttributes3 {
+
+ @XmlElement
+ SimpleBeanWithJustOneAttribute b, c;
+
+ public static Object createTestInstance() {
+ ComplexBeanWithAttributes3 instance = new ComplexBeanWithAttributes3();
+ instance.b = JsonTestHelper.createTestInstance(SimpleBeanWithJustOneAttribute.class);
+ instance.c = JsonTestHelper.createTestInstance(SimpleBeanWithJustOneAttribute.class);
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ComplexBeanWithAttributes3)) {
+ return false;
+ }
+ final ComplexBeanWithAttributes3 other = (ComplexBeanWithAttributes3) obj;
+ if (this.b != other.b && (this.b == null || !this.b.equals(other.b))) {
+ System.out.println("b differs");
+ return false;
+ }
+ if (this.c != other.c && (this.c == null || !this.c.equals(other.c))) {
+ System.out.println("c differs");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.b != null ? this.b.hashCode() : 0);
+ hash = 19 * hash + (this.c != null ? this.c.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CBWA2(%s,%s)", b, c);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes4.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes4.java
new file mode 100644
index 0000000..6e674d5
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ComplexBeanWithAttributes4.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement", "NumberEquality"})
+@XmlRootElement
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class ComplexBeanWithAttributes4 {
+
+ @XmlAttribute
+ public String a1;
+ @XmlAttribute
+ public Integer a2;
+ @XmlElement
+ public String filler1;
+ @XmlElement
+ public List<SimpleBeanWithObjectAttributes> list;
+ @XmlElement
+ public String filler2;
+ @XmlElement
+ SimpleBeanWithObjectAttributes b;
+
+ public static Object createTestInstance() {
+ ComplexBeanWithAttributes4 instance = new ComplexBeanWithAttributes4();
+ instance.b = new SimpleBeanWithObjectAttributes();
+ instance.list = new LinkedList<>();
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ComplexBeanWithAttributes4)) {
+ return false;
+ }
+ final ComplexBeanWithAttributes4 other = (ComplexBeanWithAttributes4) obj;
+ if (this.a1 != other.a1 && (this.a1 == null || !this.a1.equals(other.a1))) {
+ return false;
+ }
+ if (this.a2 != other.a2 && (this.a2 == null || !this.a2.equals(other.a2))) {
+ return false;
+ }
+ if (this.b != other.b && (this.b == null || !this.b.equals(other.b))) {
+ return false;
+ }
+ if (this.filler1 != other.filler1 && (this.filler1 == null || !this.filler1.equals(other.filler1))) {
+ return false;
+ }
+ if (this.filler2 != other.filler2 && (this.filler2 == null || !this.filler2.equals(other.filler2))) {
+ return false;
+ }
+ if (!JsonTestHelper.areCollectionsEqual(this.list, other.list)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.a1 != null ? this.a1.hashCode() : 0);
+ hash = 19 * hash + this.a2;
+ hash = 19 * hash + (this.b != null ? this.b.hashCode() : 0);
+ hash = 19 * hash + (this.filler1 != null ? this.filler1.hashCode() : 0);
+ hash = 19 * hash + (this.filler2 != null ? this.filler2.hashCode() : 0);
+ hash = 19 * hash + (this.list != null ? this.list.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("CBWA4(%s, %d, %s)", a1, a2, b).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/CustomJsonbVisibilityStrategy.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/CustomJsonbVisibilityStrategy.java
new file mode 100644
index 0000000..9d6532d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/CustomJsonbVisibilityStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import javax.json.bind.config.PropertyVisibilityStrategy;
+
+/**
+ * Custom, permissive {@link PropertyVisibilityStrategy}.
+ * <p>
+ * Used to allow JSON-B provider to "see" protected/private fields for test purposes.
+ */
+public class CustomJsonbVisibilityStrategy implements PropertyVisibilityStrategy {
+
+ @Override
+ public boolean isVisible(Field field) {
+ return true;
+ }
+
+ @Override
+ public boolean isVisible(Method method) {
+ return true;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Dog.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Dog.java
new file mode 100644
index 0000000..4de2631
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Dog.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement(name = "dog")
+public class Dog extends Animal {
+
+ public Dog() {
+ }
+
+ public Dog(final String name) {
+ super(name);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"dog\" : %s }", super.toString());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementBean.java
new file mode 100644
index 0000000..88c21e7
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementBean.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement
+public class EmptyElementBean {
+
+ public String nullOnly = null;
+
+ public static Object createTestInstance() {
+ EmptyElementBean result = new EmptyElementBean();
+ result.nullOnly = null;
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final EmptyElementBean other = (EmptyElementBean) obj;
+ if ((this.nullOnly == null) ? (other.nullOnly != null) : !this.nullOnly.equals(other.nullOnly)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 13 * hash + (this.nullOnly != null ? this.nullOnly.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{nullOnly:%s}", nullOnly);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementContainingBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementContainingBean.java
new file mode 100644
index 0000000..490c280
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EmptyElementContainingBean.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement
+public class EmptyElementContainingBean {
+
+ public EmptyElementBean emptyBean;
+ public String c;
+ public String d;
+
+ public static Object createTestInstance() {
+ EmptyElementContainingBean result = new EmptyElementContainingBean();
+ result.c = "foo";
+ result.d = "bar";
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final EmptyElementContainingBean other = (EmptyElementContainingBean) obj;
+ if (this.emptyBean != other.emptyBean && (this.emptyBean == null || !this.emptyBean.equals(other.emptyBean))) {
+ return false;
+ }
+ if ((this.c == null) ? (other.c != null) : !this.c.equals(other.c)) {
+ return false;
+ }
+ if ((this.d == null) ? (other.d != null) : !this.d.equals(other.d)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 59 * hash + (this.emptyBean != null ? this.emptyBean.hashCode() : 0);
+ hash = 59 * hash + (this.c != null ? this.c.hashCode() : 0);
+ hash = 59 * hash + (this.d != null ? this.d.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{c:%s,d:%s}", c, d);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EncodedContentBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EncodedContentBean.java
new file mode 100644
index 0000000..b4feee6
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/EncodedContentBean.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "StringEquality"})
+@XmlRootElement
+public class EncodedContentBean {
+
+ public String one;
+ public String two;
+
+ public static Object createTestInstance() {
+ EncodedContentBean instance = new EncodedContentBean();
+ instance.one = "\tone\n\tbig";
+ instance.two = "haf\u010C";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final EncodedContentBean other = (EncodedContentBean) obj;
+ if (this.one != other.one && (this.one == null || !this.one.equals(other.one))) {
+ return false;
+ }
+ if (this.two != other.two && (this.two == null || !this.two.equals(other.two))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 17 * hash + (this.one != null ? this.one.hashCode() : 0);
+ hash = 17 * hash + (this.two != null ? this.two.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ECB(%s, %s)", one, two);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/FakeArrayBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/FakeArrayBean.java
new file mode 100644
index 0000000..c42c9d0
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/FakeArrayBean.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Test case for issue#310.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "UnusedDeclaration"})
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "weight", "color", "name"
+})
+@XmlRootElement()
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class FakeArrayBean {
+
+ protected List<String> weight;
+ @XmlElement(required = true)
+ protected String color;
+ @XmlElement(required = true)
+ protected String name;
+
+ public List<String> getWeight() {
+ if (weight == null) {
+ weight = new ArrayList<>();
+ }
+ return this.weight;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String value) {
+ this.color = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ public static Object createTestInstance() {
+ FakeArrayBean result = new FakeArrayBean();
+
+ result.getWeight().add("1kg");
+ result.getWeight().add("2kg");
+ result.setColor("red");
+ result.setName("bumper");
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final FakeArrayBean other = (FakeArrayBean) obj;
+ if (this.weight != other.weight && (this.weight == null || !this.weight.equals(other.weight))) {
+ return false;
+ }
+ if ((this.color == null) ? (other.color != null) : !this.color.equals(other.color)) {
+ return false;
+ }
+ if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 29 * hash + (this.weight != null ? this.weight.hashCode() : 0);
+ hash = 29 * hash + (this.color != null ? this.color.hashCode() : 0);
+ hash = 29 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{name:%s, color:%s, weights:%s}", name, color, weight);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/IntArray.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/IntArray.java
new file mode 100644
index 0000000..742865f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/IntArray.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Arrays;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "intArray")
+public class IntArray {
+
+ public int[] intArray;
+
+ public Integer[] integerArray;
+
+ public int number;
+
+ public IntArray() {
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final IntArray other = (IntArray) obj;
+ if (!Arrays.equals(this.intArray, other.intArray)) {
+ return false;
+ }
+ if (!Arrays.deepEquals(this.integerArray, other.integerArray)) {
+ return false;
+ }
+ if (this.number != other.number) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 89 * hash + Arrays.hashCode(this.intArray);
+ hash = 89 * hash + Arrays.deepHashCode(this.integerArray);
+ hash = 89 * hash + this.number;
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"intArray\":%s, \"integerArray\":%s, \"number\":%d}", Arrays.toString(intArray),
+ Arrays.toString(integerArray), number);
+ }
+
+ public static Object createTestInstance() {
+ IntArray result = new IntArray();
+
+ result.number = 8;
+ result.intArray = new int[]{4};
+ result.integerArray = new Integer[]{3};
+
+ return result;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Jersey1199List.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Jersey1199List.java
new file mode 100644
index 0000000..f293625
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Jersey1199List.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Formatter;
+
+import javax.json.bind.annotation.JsonbTypeAdapter;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.Jersey1199Test;
+
+/**
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"UnusedDeclaration", "NumberEquality", "SimplifiableIfStatement"})
+@XmlRootElement
+public class Jersey1199List {
+
+ public static Object createTestInstance() {
+ final ColorHolder obj1 = new ColorHolder(EnumSet.of(Color.RED, Color.BLUE));
+ final ColorHolder obj2 = new ColorHolder(EnumSet.of(Color.GREEN));
+
+ return new Jersey1199List(new Object[]{obj1, obj2});
+ }
+
+ private Object[] objects;
+ private Integer offset;
+ private Integer total;
+
+ public Jersey1199List() {
+ }
+
+ public Jersey1199List(final Object[] objects) {
+ this.objects = objects;
+ this.offset = 0;
+ this.total = objects.length;
+ }
+
+ // Jackson 1
+ @org.codehaus.jackson.annotate.JsonTypeInfo(
+ use = org.codehaus.jackson.annotate.JsonTypeInfo.Id.NAME,
+ include = org.codehaus.jackson.annotate.JsonTypeInfo.As.PROPERTY)
+ @org.codehaus.jackson.annotate.JsonSubTypes({
+ @org.codehaus.jackson.annotate.JsonSubTypes.Type(value = ColorHolder.class)
+ })
+ // Jackson 2
+ @com.fasterxml.jackson.annotation.JsonTypeInfo(
+ use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME,
+ include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY)
+ @com.fasterxml.jackson.annotation.JsonSubTypes({
+ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = ColorHolder.class)
+ })
+ // JSON-B
+ @JsonbTypeAdapter(Jersey1199Test.JsonbObjectToColorHolderAdapter.class)
+ public Object[] getObjects() {
+ return objects;
+ }
+
+ public void setObjects(final Object[] objects) {
+ this.objects = objects;
+ }
+
+ public Integer getOffset() {
+ return offset;
+ }
+
+ public void setOffset(final Integer offset) {
+ this.offset = offset;
+ }
+
+ public Integer getTotal() {
+ return total;
+ }
+
+ public void setTotal(final Integer total) {
+ this.total = total;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof Jersey1199List)) {
+ return false;
+ }
+
+ final Jersey1199List other = (Jersey1199List) obj;
+
+ if (this.total != other.total && (this.total == null || !this.total.equals(other.total))) {
+ return false;
+ }
+ if (this.offset != other.offset && (this.offset == null || !this.offset.equals(other.offset))) {
+ return false;
+ }
+
+ return Arrays.equals(this.objects, other.objects);
+ }
+
+ @Override
+ public String toString() {
+ return new Formatter().format("Jersey1199List(%s, %d, %d)", Arrays.toString(objects), offset, total).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 43;
+ hash += (offset != null ? 17 * offset : 0);
+ hash += (total != null ? 17 * total : 0);
+ hash += Arrays.hashCode(objects);
+ return hash;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListAndNonListBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListAndNonListBean.java
new file mode 100644
index 0000000..4b4fbc8
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListAndNonListBean.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "StringEquality"})
+@XmlRootElement
+public class ListAndNonListBean {
+
+ public List<String> a;
+ public String d;
+
+ public static Object createTestInstance() {
+ ListAndNonListBean instance = new ListAndNonListBean();
+ instance.a = new LinkedList<String>();
+ instance.a.add("1");
+ instance.d = "2";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ListAndNonListBean other = (ListAndNonListBean) obj;
+ if (this.a != other.a && (this.a == null || !this.a.equals(other.a))) {
+ return false;
+ }
+ if (this.d != other.d && (this.d == null || !this.d.equals(other.d))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 47 * hash + (this.a != null ? this.a.hashCode() : 0);
+ hash = 47 * hash + (this.d != null ? this.d.hashCode() : 0);
+ return hash;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListEmptyBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListEmptyBean.java
new file mode 100644
index 0000000..4ff613b
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListEmptyBean.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author mchenryc
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement(name = "listEmptyBean")
+public class ListEmptyBean {
+
+ private List<String> empty;
+
+ public static Object createTestInstance() {
+ ListEmptyBean instance = new ListEmptyBean();
+ instance.empty = new LinkedList<>();
+ return instance;
+ }
+
+ public List<String> getEmpty() {
+ return empty;
+ }
+
+ public void setEmpty(List<String> empty) {
+ this.empty = empty;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ListEmptyBean other = (ListEmptyBean) obj;
+ return this.empty == other.empty
+ || (JsonTestHelper.isCollectionEmpty(this.empty) && JsonTestHelper.isCollectionEmpty(other.empty))
+ || (this.empty != null && this.empty.equals(other.empty));
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + (this.empty != null ? this.empty.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("LwNB(n=%d,isNull:%s)", (empty != null) ? empty.size() : 0, (empty == null)).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListWrapperBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListWrapperBean.java
new file mode 100644
index 0000000..03bd242
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/ListWrapperBean.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "item")
+public class ListWrapperBean {
+
+ public List<String> property;
+
+ public static Object createTestInstance() {
+ return new ListWrapperBean();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ListWrapperBean other = (ListWrapperBean) obj;
+ if ((this.property != other.property
+ && JsonTestHelper.isCollectionEmpty(this.property) != JsonTestHelper.isCollectionEmpty(other.property))
+ && (this.property == null || !this.property.equals(other.property))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 23 * hash + (this.property != null ? this.property.hashCode() : 0);
+ return hash;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyError.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyError.java
new file mode 100644
index 0000000..46ab86a
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyError.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>Java class for anonymous complex type.
+ * <p/>
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p/>
+ * <pre>
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * <element name="desc" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "id", "desc"
+})
+@XmlRootElement(name = "myError")
+public class MyError {
+
+ @XmlElement(required = true)
+ protected String id;
+ @XmlElement(required = true)
+ protected String desc;
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is
+ * {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is
+ * {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the desc property.
+ *
+ * @return possible object is
+ * {@link String }
+ */
+ public String getDesc() {
+ return desc;
+ }
+
+ /**
+ * Sets the value of the desc property.
+ *
+ * @param value allowed object is
+ * {@link String }
+ */
+ public void setDesc(String value) {
+ this.desc = value;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final MyError other = (MyError) obj;
+ if ((this.id == null) ? (other.id != null) : !this.id.equals(other.id)) {
+ return false;
+ }
+ if ((this.desc == null) ? (other.desc != null) : !this.desc.equals(other.desc)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + (this.id != null ? this.id.hashCode() : 0);
+ hash = 19 * hash + (this.desc != null ? this.desc.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ sb.append(getId());
+ sb.append(',');
+ sb.append(getDesc());
+ sb.append('}');
+ return sb.toString();
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyMessage.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyMessage.java
new file mode 100644
index 0000000..923b761
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyMessage.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>Java class for anonymous complex type.
+ * <p/>
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p/>
+ * <pre>
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "id", "text"
+})
+@XmlRootElement(name = "myMessage")
+public class MyMessage {
+
+ @XmlElement(required = true)
+ protected String id;
+ @XmlElement(required = true)
+ protected String text;
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is
+ * {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is
+ * {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the text property.
+ *
+ * @return possible object is
+ * {@link String }
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the value of the text property.
+ *
+ * @param value allowed object is
+ * {@link String }
+ */
+ public void setText(String value) {
+ this.text = value;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final MyMessage other = (MyMessage) obj;
+ if ((this.id == null) ? (other.id != null) : !this.id.equals(other.id)) {
+ return false;
+ }
+ if ((this.text == null) ? (other.text != null) : !this.text.equals(other.text)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 47 * hash + (this.id != null ? this.id.hashCode() : 0);
+ hash = 47 * hash + (this.text != null ? this.text.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ sb.append(getId());
+ sb.append(',');
+ sb.append(getText());
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyResponse.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyResponse.java
new file mode 100644
index 0000000..10f53d2
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/MyResponse.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>Java class for anonymous complex type.
+ * <p/>
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p/>
+ * <pre>
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://test.jaxb.com}myMessage" maxOccurs="unbounded" minOccurs="0"/>
+ * <element ref="{http://test.jaxb.com}myError"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "myMessage", "myError"
+})
+@XmlRootElement(name = "myResponse")
+@JsonbVisibility(CustomJsonbVisibilityStrategy.class)
+public class MyResponse {
+
+ @XmlElement(namespace = "http://test.jaxb.com")
+ protected List<MyMessage> myMessage;
+ @XmlElement(namespace = "http://test.jaxb.com", required = true)
+ protected MyError myError;
+
+ /**
+ * Gets the value of the myMessage property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the myMessage property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getMyMessage().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link MyMessage }
+ */
+ public List<MyMessage> getMyMessage() {
+ if (myMessage == null) {
+ myMessage = new ArrayList<>();
+ }
+ return this.myMessage;
+ }
+
+ /**
+ * Gets the value of the myError property.
+ *
+ * @return possible object is
+ * {@link MyError }
+ */
+ public MyError getMyError() {
+ return myError;
+ }
+
+ /**
+ * Sets the value of the myError property.
+ *
+ * @param value allowed object is
+ * {@link MyError }
+ */
+ public void setMyError(MyError value) {
+ this.myError = value;
+ }
+
+ public static Object createTestInstance() {
+
+ MyResponse myResponse = new MyResponse();
+
+ MyMessage msg = new MyMessage();
+ msg.setId("0");
+ msg.setText("ok");
+ MyMessage msg2 = new MyMessage();
+ msg2.setId("1");
+ msg2.setText("ok");
+ myResponse.getMyMessage().add(msg);
+ myResponse.getMyMessage().add(msg2);
+
+ MyError err = new MyError();
+ err.setId("-1");
+ err.setDesc("error");
+ myResponse.setMyError(err);
+ return myResponse;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final MyResponse other = (MyResponse) obj;
+ if (this.myMessage != other.myMessage && (this.myMessage == null || !this.myMessage.equals(other.myMessage))) {
+ return false;
+ }
+ if (this.myError != other.myError && (this.myError == null || !this.myError.equals(other.myError))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 97 * hash + (this.myMessage != null ? this.myMessage.hashCode() : 0);
+ hash = 97 * hash + (this.myError != null ? this.myError.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ sb.append(getMyMessage());
+ sb.append(",");
+ sb.append(getMyError());
+ sb.append("}");
+ return sb.toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBean.java
new file mode 100644
index 0000000..acbb2c6
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBean.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+
+@SuppressWarnings({"RedundantIfStatement", "UnusedDeclaration"})
+@XmlRootElement
+public class NamespaceBean {
+
+ @XmlElement
+ public String a;
+
+ @XmlElement(namespace = "http://example.com")
+ public String b;
+
+ public NamespaceBean() {
+ }
+
+ public NamespaceBean(String a, String b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final NamespaceBean other = (NamespaceBean) obj;
+ if ((this.a == null) ? (other.a != null) : !this.a.equals(other.a)) {
+ return false;
+ }
+ if ((this.b == null) ? (other.b != null) : !this.b.equals(other.b)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 37 * hash + (this.a != null ? this.a.hashCode() : 0);
+ hash = 37 * hash + (this.b != null ? this.b.hashCode() : 0);
+ return hash;
+ }
+
+ public static Object createTestInstance() {
+ return new NamespaceBean("foo", "bar");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{a:%s, b:%s", a, b);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBeanWithAttribute.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBeanWithAttribute.java
new file mode 100644
index 0000000..74254f8
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NamespaceBeanWithAttribute.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"UnusedDeclaration", "RedundantIfStatement"})
+@XmlRootElement
+public class NamespaceBeanWithAttribute {
+
+ @XmlAttribute(namespace = "http://example.com")
+ public String attr;
+
+ @XmlElement
+ public String a;
+
+ @XmlElement(namespace = "http://example.com")
+ public String b;
+
+ public NamespaceBeanWithAttribute() {
+ }
+
+ public NamespaceBeanWithAttribute(String attr, String a, String b) {
+ this.attr = attr;
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final NamespaceBeanWithAttribute other = (NamespaceBeanWithAttribute) obj;
+ if ((this.attr == null) ? (other.attr != null) : !this.attr.equals(other.attr)) {
+ return false;
+ }
+ if ((this.a == null) ? (other.a != null) : !this.a.equals(other.a)) {
+ return false;
+ }
+ if ((this.b == null) ? (other.b != null) : !this.b.equals(other.b)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 37 * hash + (this.attr != null ? this.attr.hashCode() : 0);
+ hash = 37 * hash + (this.a != null ? this.a.hashCode() : 0);
+ hash = 37 * hash + (this.b != null ? this.b.hashCode() : 0);
+ return hash;
+ }
+
+ public static Object createTestInstance() {
+ return new NamespaceBeanWithAttribute("value", "foo", "bar");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{attr:%s, a:%s, b:%s", attr, a, b);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NullStringBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NullStringBean.java
new file mode 100644
index 0000000..ee855d3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/NullStringBean.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement
+public class NullStringBean {
+
+ @XmlElement(nillable = true)
+ public String nullString = "not null to test if set to null works";
+
+ public static Object createTestInstance() {
+ return new NullStringBean();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final NullStringBean other = (NullStringBean) obj;
+ if ((this.nullString == null) ? (other.nullString != null) : !this.nullString.equals(other.nullString)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.nullString != null ? this.nullString.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{nullString:%s}", quoteDelimitedStringOrNull(nullString));
+ }
+
+ private String quoteDelimitedStringOrNull(String string) {
+ return (string == null) ? "null" : String.format("\"%s\"", string);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Person.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Person.java
new file mode 100644
index 0000000..f578874
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/Person.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Arrays;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jay Feenan (jay.feenan at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement(name = "person")
+@XmlAccessorType(XmlAccessType.PROPERTY)
+@XmlType(propOrder = {"name", "children"})
+public class Person {
+
+ public static Object createTestInstance() {
+ Person daughter = new Person();
+ daughter.setName("Jill Schmo");
+
+ Person son = new Person();
+ son.setName("Jack Schmo");
+
+ Person person = new Person();
+ person.setName("Joe Schmo");
+ person.setChildren(new Person[]{daughter, son});
+
+ return person;
+ }
+
+ @SuppressWarnings("SimplifiableIfStatement")
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if ((this.m_name == null) ? (other.m_name != null) : !this.m_name.equals(other.m_name)) {
+ return false;
+ }
+ return JsonTestHelper.areArraysEqual(m_children, other.m_children);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 19 * hash + (this.m_name != null ? this.m_name.hashCode() : 0);
+ hash = 19 * hash + (this.m_children != null ? Arrays.hashCode(this.m_children) : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{person: %s, %s}", m_name, Arrays.toString(m_children));
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public void setName(String name) {
+ m_name = name;
+ }
+
+ @XmlElementWrapper(name = "children")
+ @XmlElement(name = "child")
+ public Person[] getChildren() {
+ return m_children;
+ }
+
+ public void setChildren(Person[] children) {
+ m_children = children;
+ }
+
+ private String m_name;
+ private Person[] m_children;
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/PureCharDataBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/PureCharDataBean.java
new file mode 100644
index 0000000..bc21834
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/PureCharDataBean.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "StringEquality"})
+@XmlRootElement
+public class PureCharDataBean {
+
+ @XmlValue
+ public String content;
+
+ public static Object createTestInstance() {
+ PureCharDataBean instance = new PureCharDataBean();
+ instance.content = "some textual content";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PureCharDataBean other = (PureCharDataBean) obj;
+ if (this.content != other.content && (this.content == null || !this.content.equals(other.content))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 59 * hash + (this.content != null ? this.content.hashCode() : 0);
+ return hash;
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/RegisterMessage.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/RegisterMessage.java
new file mode 100644
index 0000000..68b5330
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/RegisterMessage.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author David Kaspar
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement
+public final class RegisterMessage {
+
+ @XmlAttribute
+ public String agentUID;
+
+ @XmlAttribute
+ public long requestTime;
+
+ public RegisterMessage() {
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final RegisterMessage other = (RegisterMessage) obj;
+ if ((this.agentUID == null) ? (other.agentUID != null) : !this.agentUID.equals(other.agentUID)) {
+ return false;
+ }
+ if (this.requestTime != other.requestTime) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 89 * hash + (this.agentUID != null ? this.agentUID.hashCode() : 0);
+ hash = 89 * hash + (int) (this.requestTime ^ (this.requestTime >>> 32));
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{\"agentUID\":\"%s\", \"requestTime\":%d}", agentUID, requestTime);
+ }
+
+ public static Object createTestInstance() {
+ RegisterMessage rm = new RegisterMessage();
+ rm.agentUID = "agentKocka";
+ rm.requestTime = 1234L;
+ return rm;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBean.java
new file mode 100644
index 0000000..79251da
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBean.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "StringEquality"})
+@XmlRootElement(name = "DummyOne")
+public class SimpleBean {
+
+ @XmlElement
+ public String child;
+
+ public static Object createTestInstance() {
+ SimpleBean instance = new SimpleBean();
+ instance.child = "simple";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleBean other = (SimpleBean) obj;
+ if (this.child != other.child && (this.child == null || !this.child.equals(other.child))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (this.child != null ? this.child.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("SB(%s)", child).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithAttributes.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithAttributes.java
new file mode 100644
index 0000000..e086739
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithAttributes.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Formatter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement"})
+@XmlRootElement
+public class SimpleBeanWithAttributes {
+
+ @XmlAttribute
+ public URI uri;
+ public String s1;
+ @XmlAttribute
+ public int i;
+ @XmlAttribute
+ public String j;
+
+ public SimpleBeanWithAttributes() {
+ }
+
+ public static Object createTestInstance() {
+ SimpleBeanWithAttributes instance = new SimpleBeanWithAttributes();
+ instance.s1 = "hi there";
+ instance.i = 312;
+ instance.j = "bumper";
+
+ try {
+ instance.uri = new URI("http://localhost:8080/jedna/bedna/");
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(SimpleBeanWithAttributes.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleBeanWithAttributes other = (SimpleBeanWithAttributes) obj;
+ if (this.s1 != other.s1 && (this.s1 == null || !this.s1.equals(other.s1))) {
+ return false;
+ }
+ if (this.j != other.j && (this.j == null || !this.j.equals(other.j))) {
+ return false;
+ }
+ if (this.uri != other.uri && (this.uri == null || !this.uri.equals(other.uri))) {
+ return false;
+ }
+ if (this.i != other.i) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ if (null != s1) {
+ hash += 17 * s1.hashCode();
+ }
+ if (null != j) {
+ hash += 17 * j.hashCode();
+ }
+ if (null != uri) {
+ hash += 17 * uri.hashCode();
+ }
+ hash += 13 * i;
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("SBWA(%s,%d,%s,%s)", s1, i, j, uri).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttribute.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttribute.java
new file mode 100644
index 0000000..b3207ab
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttribute.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement
+public class SimpleBeanWithJustOneAttribute {
+
+ @XmlAttribute
+ public URI uri;
+
+ public SimpleBeanWithJustOneAttribute() {
+ }
+
+ public static Object createTestInstance() {
+ SimpleBeanWithJustOneAttribute instance = new SimpleBeanWithJustOneAttribute();
+
+ try {
+ instance.uri = new URI("http://localhost:8080/jedna/bedna/");
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(SimpleBeanWithJustOneAttribute.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleBeanWithJustOneAttribute other = (SimpleBeanWithJustOneAttribute) obj;
+ if (this.uri != other.uri && (this.uri == null || !this.uri.equals(other.uri))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ if (null != uri) {
+ hash += 17 * uri.hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("SBWJOA(%s)", uri);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttributeAndValue.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttributeAndValue.java
new file mode 100644
index 0000000..45c794f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithJustOneAttributeAndValue.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"RedundantIfStatement", "StringEquality"})
+@XmlRootElement
+public class SimpleBeanWithJustOneAttributeAndValue {
+
+ @XmlAttribute
+ public URI uri;
+ @XmlValue
+ public String value;
+
+ public SimpleBeanWithJustOneAttributeAndValue() {
+ }
+
+ public static Object createTestInstance() {
+ SimpleBeanWithJustOneAttributeAndValue instance = new SimpleBeanWithJustOneAttributeAndValue();
+
+ try {
+ instance.uri = new URI("http://localhost:8080/jedna/bedna/");
+ instance.value = "characters";
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(SimpleBeanWithJustOneAttributeAndValue.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleBeanWithJustOneAttributeAndValue other = (SimpleBeanWithJustOneAttributeAndValue) obj;
+ if (this.uri != other.uri && (this.uri == null || !this.uri.equals(other.uri))) {
+ return false;
+ }
+ if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ if (null != uri) {
+ hash += 17 * uri.hashCode();
+ }
+ if (null != value) {
+ hash += 17 * value.hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("SBWJOAV(%s,%s)", uri, value);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithObjectAttributes.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithObjectAttributes.java
new file mode 100644
index 0000000..bc10df1
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleBeanWithObjectAttributes.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.net.URI;
+import java.util.Formatter;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement", "NumberEquality"})
+@XmlRootElement
+public class SimpleBeanWithObjectAttributes {
+
+ @XmlAttribute
+ public URI uri;
+ public String s1;
+ @XmlAttribute
+ public Integer i;
+ @XmlAttribute
+ public String j;
+
+ public SimpleBeanWithObjectAttributes() {
+ }
+
+ public static Object createTestInstance() {
+ return new SimpleBeanWithObjectAttributes();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleBeanWithObjectAttributes other = (SimpleBeanWithObjectAttributes) obj;
+ if (this.s1 != other.s1 && (this.s1 == null || !this.s1.equals(other.s1))) {
+ return false;
+ }
+ if (this.j != other.j && (this.j == null || !this.j.equals(other.j))) {
+ return false;
+ }
+ if (this.uri != other.uri && (this.uri == null || !this.uri.equals(other.uri))) {
+ return false;
+ }
+ if (this.i != other.i && (this.i == null || !this.i.equals(other.i))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ if (null != s1) {
+ hash += 17 * s1.hashCode();
+ }
+ if (null != j) {
+ hash += 17 * j.hashCode();
+ }
+ if (null != uri) {
+ hash += 17 * uri.hashCode();
+ }
+ hash += 13 * i;
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("SBWOA(%s,%d,%s,%s)", s1, i, j, uri).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleXmlTypeBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleXmlTypeBean.java
new file mode 100644
index 0000000..82cf9ac
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SimpleXmlTypeBean.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Formatter;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement"})
+@XmlType
+public class SimpleXmlTypeBean {
+
+ @XmlElement
+ public String child;
+
+ public static Object createTestInstance() {
+ SimpleXmlTypeBean instance = new SimpleXmlTypeBean();
+ instance.child = "simple";
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SimpleXmlTypeBean other = (SimpleXmlTypeBean) obj;
+ if (this.child != other.child && (this.child == null || !this.child.equals(other.child))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (this.child != null ? this.child.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (new Formatter()).format("SETB(%s)", child).toString();
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SingleItemListWrapperBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SingleItemListWrapperBean.java
new file mode 100644
index 0000000..f7f14a0
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/SingleItemListWrapperBean.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "singleItemListWrapper")
+public class SingleItemListWrapperBean {
+
+ public List<String> singleItemList;
+
+ public static Object createTestInstance() {
+ SingleItemListWrapperBean instance = new SingleItemListWrapperBean();
+ instance.singleItemList = new LinkedList<>();
+ instance.singleItemList.add("1");
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SingleItemListWrapperBean other = (SingleItemListWrapperBean) obj;
+ if (this.singleItemList != other.singleItemList && (this.singleItemList == null || !this.singleItemList
+ .equals(other.singleItemList))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 59 * hash + (this.singleItemList != null ? this.singleItemList.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{singleItemListWrapperBean:{l:%s}}", singleItemList);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TreeModel.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TreeModel.java
new file mode 100644
index 0000000..bc9dc0f
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TreeModel.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"UnusedDeclaration", "RedundantIfStatement"})
+@XmlRootElement
+public class TreeModel {
+
+ @SuppressWarnings({"UnusedDeclaration", "StringEquality", "RedundantIfStatement"})
+ public static class Node {
+
+ @XmlElement
+ public String label;
+ @XmlElement
+ public boolean expanded;
+ @XmlElement
+ public List<Node> children;
+
+ public Node() {
+ this("dummy node", null);
+ }
+
+ public Node(String label) {
+ this(label, null);
+ }
+
+ public Node(String label, Collection<Node> children) {
+ this.label = label;
+ if (!JsonTestHelper.isCollectionEmpty(children)) {
+ this.children = new LinkedList<Node>();
+ this.children.addAll(children);
+ expanded = true;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 13;
+ result += 17 * label.hashCode();
+ if (!JsonTestHelper.isCollectionEmpty(children)) {
+ for (Node n : children) {
+ result = 5 + 17 * n.hashCode();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Node)) {
+ return false;
+ }
+ final Node other = (Node) obj;
+ if (this.label != other.label && (this.label == null || !this.label.equals(other.label))) {
+ return false;
+ }
+ if ((this.children != other.children
+ && JsonTestHelper.isCollectionEmpty(this.children) != JsonTestHelper.isCollectionEmpty(other.children))
+ && (this.children == null || !this.children.equals(other.children))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ String result = "(" + label + ":";
+ if (!JsonTestHelper.isCollectionEmpty(children)) {
+ for (Node n : children) {
+ result += n.toString();
+ }
+ return result + ")";
+ } else {
+ return result + "0 children)";
+ }
+ }
+ }
+
+ @XmlElement
+ public Node root;
+
+ public TreeModel() {
+ }
+
+ public TreeModel(Node root) {
+ this.root = root;
+ }
+
+ public static Object createTestInstance() {
+ TreeModel instance = new TreeModel();
+ instance.root = new Node();
+ return instance;
+ }
+
+ @Override
+ public int hashCode() {
+ if (null != root) {
+ return 7 + root.hashCode();
+ } else {
+ return 7;
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TreeModel)) {
+ return false;
+ }
+ final TreeModel other = (TreeModel) obj;
+ if (this.root != other.root && (this.root == null || !this.root.equals(other.root))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return (null != root) ? root.toString() : "(NULL_ROOT)";
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TwoListsWrapperBean.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TwoListsWrapperBean.java
new file mode 100644
index 0000000..99b76f0
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/TwoListsWrapperBean.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings("RedundantIfStatement")
+@XmlRootElement(name = "item2")
+public class TwoListsWrapperBean {
+
+ public List<String> property1, property2;
+
+ public static Object createTestInstance() {
+ TwoListsWrapperBean instance = new TwoListsWrapperBean();
+ instance.property1 = new LinkedList<String>();
+ instance.property1.add("a1");
+ instance.property1.add("a1");
+ instance.property2 = new LinkedList<String>();
+ instance.property2.add("b1");
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TwoListsWrapperBean other = (TwoListsWrapperBean) obj;
+ if (this.property1 != other.property1 && (this.property1 == null || !this.property1.equals(other.property1))) {
+ return false;
+ }
+ if (this.property2 != other.property2 && (this.property2 == null || !this.property2.equals(other.property2))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 59 * hash + (this.property1 != null ? this.property1.hashCode() : 0);
+ hash = 59 * hash + (this.property2 != null ? this.property2.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{twoListsWrapperBean:{property1:%s, property2:%s}}", property1, property2);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/User.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/User.java
new file mode 100644
index 0000000..94f0649
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/User.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import javax.json.bind.annotation.JsonbTransient;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@SuppressWarnings({"StringEquality", "RedundantIfStatement", "UnusedDeclaration"})
+@XmlRootElement
+public class User {
+
+ @XmlElement(name = "userid")
+ public String id;
+ public String name;
+ @XmlTransient
+ @JsonbTransient
+ public String password;
+
+ public User() {
+ }
+
+ public User(String id, String name, String password) {
+ this.id = id;
+ this.name = name;
+ this.password = password;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof User)) {
+ return false;
+ }
+ final User other = (User) obj;
+ if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) {
+ return false;
+ }
+ if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ if (null != id) {
+ hash = 17 * hash + id.hashCode();
+ }
+ if (null != name) {
+ hash = 17 * hash + name.hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "User(" + id + ", " + name + ")";
+ }
+
+ public static Object createTestInstance() {
+ return new User("1621", "Grotefend", "Persepolis");
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/UserTable.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/UserTable.java
new file mode 100644
index 0000000..a37d11c
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/UserTable.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.json.JsonTestHelper;
+
+/**
+ * Note: With MOXy we need to ensure that collections (a list in this case) with predefined values (assigned to the list during
+ * object initialization) are either uninitialized or empty during the object creation, otherwise there is a possibility that
+ * these default values are doubled in the list (list is filled with default values when a new instance is created and after
+ * unmarshalling XML/JSON stream additional elements are added to this list - MOXy doesn't override the existing list with a
+ * new one created during unmarshalling).
+ * <p/>
+ * Workaround: Set {@link javax.xml.bind.annotation.XmlAccessorType} to {@link javax.xml.bind.annotation.XmlAccessType#FIELD},
+ * do not initialize the list in the default constructor
+ * (field initializer) and assign the value to the list that should contain predefined values manually (in this case the value
+ * object is represented by {@code #DEFAULT_HEADERS}).
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class UserTable {
+
+ @SuppressWarnings("RedundantIfStatement")
+ public static class JMakiTableHeader {
+
+ public String id;
+ public String label;
+
+ public JMakiTableHeader() {
+ }
+
+ public JMakiTableHeader(String id, String label) {
+ this.id = id;
+ this.label = label;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 13;
+ hash = id != null ? 29 * id.hashCode() : hash;
+ hash = label != null ? 29 * label.hashCode() : hash;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JMakiTableHeader)) {
+ return false;
+ }
+ JMakiTableHeader that = (JMakiTableHeader) obj;
+
+ if ((id != null && !id.equals(that.id)) && that.id != null) {
+ return false;
+ }
+ if ((label != null && !label.equals(that.label)) && that.label != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "JMakiTableHeader(id = " + id + ", label = " + label + ")";
+ }
+ }
+
+ public static Object createTestInstance() {
+ UserTable instance = new UserTable();
+ instance.rows = new LinkedList<User>();
+ instance.rows.add(JsonTestHelper.createTestInstance(User.class));
+ instance.columns = DEFAULT_HEADERS;
+ return instance;
+ }
+
+ public static Object createTestInstance2() {
+ UserTable instance = new UserTable();
+ instance.rows = new LinkedList<User>();
+ instance.rows.add(JsonTestHelper.createTestInstance(User.class));
+ instance.addColumn(new JMakiTableHeader("password", "Password"));
+ return instance;
+ }
+
+ static List<JMakiTableHeader> initHeaders() {
+ List<JMakiTableHeader> headers = new LinkedList<JMakiTableHeader>();
+ headers.add(new JMakiTableHeader("userid", "UserID"));
+ headers.add(new JMakiTableHeader("name", "User Name"));
+ return Collections.unmodifiableList(headers);
+ }
+
+ public static final List<JMakiTableHeader> DEFAULT_HEADERS = initHeaders();
+
+ private List<JMakiTableHeader> columns;
+ private List<User> rows;
+
+ public UserTable() {
+ }
+
+ public UserTable(List<User> users) {
+ this.rows = new LinkedList<User>();
+ this.rows.addAll(users);
+ this.columns = DEFAULT_HEADERS;
+ }
+
+ public void addColumn(final JMakiTableHeader column) {
+ getColumns().add(column);
+ }
+
+ public List<JMakiTableHeader> getColumns() {
+ if (columns == null) {
+ columns = new LinkedList<JMakiTableHeader>(DEFAULT_HEADERS);
+ }
+ return columns;
+ }
+
+ public void setColumns(final List<JMakiTableHeader> columns) {
+ this.columns = columns;
+ }
+
+ public List<User> getRows() {
+ return rows;
+ }
+
+ public void setRows(final List<User> rows) {
+ this.rows = rows;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof UserTable)) {
+ return false;
+ }
+ final UserTable other = (UserTable) obj;
+
+ return JsonTestHelper.areCollectionsEqual(this.rows, other.rows)
+ && JsonTestHelper.areCollectionsEqual(this.columns, other.columns);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 16;
+ if (null != rows) {
+ for (User u : rows) {
+ hash = 17 * hash + u.hashCode();
+ }
+ }
+ if (null != columns) {
+ for (JMakiTableHeader u : columns) {
+ hash = 17 * hash + u.hashCode();
+ }
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("UserTable(%s,%s)", rows, columns);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimal.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimal.java
new file mode 100644
index 0000000..e8bd11a
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimal.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity.pojo;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+// Jackson 1
+@org.codehaus.jackson.annotate.JsonTypeInfo(
+ use = org.codehaus.jackson.annotate.JsonTypeInfo.Id.NAME,
+ include = org.codehaus.jackson.annotate.JsonTypeInfo.As.PROPERTY)
+@org.codehaus.jackson.annotate.JsonSubTypes({
+ @org.codehaus.jackson.annotate.JsonSubTypes.Type(value = PojoCat.class),
+ @org.codehaus.jackson.annotate.JsonSubTypes.Type(value = PojoDog.class) })
+// Jackson 2
+@com.fasterxml.jackson.annotation.JsonTypeInfo(
+ use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME,
+ include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY)
+@com.fasterxml.jackson.annotation.JsonSubTypes({
+ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = PojoCat.class),
+ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = PojoDog.class) })
+@SuppressWarnings("RedundantIfStatement")
+public class PojoAnimal {
+
+ public String name;
+
+ public PojoAnimal() {
+ }
+
+ public PojoAnimal(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PojoAnimal other = (PojoAnimal) obj;
+ if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"name\":\"%s\"}", name);
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimalList.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimalList.java
new file mode 100644
index 0000000..1f082f4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoAnimalList.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity.pojo;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("RedundantIfStatement")
+public class PojoAnimalList {
+
+ public List<PojoAnimal> animals;
+
+ public static Object createTestInstance() {
+ final PojoAnimalList aList = new PojoAnimalList();
+ aList.animals = new LinkedList<>();
+ aList.animals.add(new PojoDog("Fifi"));
+ aList.animals.add(new PojoCat("Daisy"));
+ return aList;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PojoAnimalList other = (PojoAnimalList) obj;
+ if (this.animals != other.animals && (this.animals == null || !this.animals.equals(other.animals))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 89 * hash + (this.animals != null ? this.animals.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return (animals != null) ? animals.toString() : null;
+ }
+
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoCat.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoCat.java
new file mode 100644
index 0000000..91c1ec4
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoCat.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity.pojo;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class PojoCat extends PojoAnimal {
+
+ private String nickName;
+
+ public PojoCat() {
+ }
+
+ public PojoCat(final String name) {
+ super(name);
+ }
+
+ public PojoCat(final String name, final String nickName) {
+ super(name);
+ this.nickName = nickName;
+ }
+
+ public void setNickName(final String nickName) {
+ this.nickName = nickName;
+ }
+
+ public String getNickName() {
+ return this.nickName;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"cat\" : %s , %s}", super.toString(), this.nickName);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoDog.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoDog.java
new file mode 100644
index 0000000..a4c4d59
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/json/entity/pojo/PojoDog.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.json.entity.pojo;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class PojoDog extends PojoAnimal {
+
+ public PojoDog() {
+ }
+
+ public PojoDog(final String name) {
+ super(name);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{ \"dog\" : %s }", super.toString());
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterCloseTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterCloseTest.java
new file mode 100644
index 0000000..47cf3d5
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterCloseTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.sse.OutboundSseEvent;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseBroadcaster;
+import javax.ws.rs.sse.SseEventSink;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test broadcaster behaviour when closing.
+ *
+ * Proves, that broadcaster attempts to send the messages remaining in the buffer after it receives the close signal.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class BroadcasterCloseTest extends JerseyTest {
+
+ private static final int SLOW_SUBSCRIBER_LATENCY = 200;
+ private static final int MSG_COUNT = 8;
+ private static final CountDownLatch onCompleteLatch = new CountDownLatch(1);
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SseResource.class);
+ }
+
+ @Path("events")
+ @Singleton
+ public static class SseResource {
+ private final Sse sse;
+ private final SseBroadcaster broadcaster;
+ private final List<String> data = new ArrayList<>();
+
+ public SseResource(@Context final Sse sse) {
+ this.sse = sse;
+ this.broadcaster = sse.newBroadcaster();
+ this.broadcaster.register(new SseEventSink() {
+
+ volatile boolean closed = false;
+
+ @Override
+ public boolean isClosed() {
+ return closed;
+ }
+
+ @Override
+ public CompletionStage<?> send(OutboundSseEvent event) {
+ try {
+ Thread.sleep(SLOW_SUBSCRIBER_LATENCY);
+ } catch (InterruptedException e) {
+ System.out.println("Slow subscriber's sleep was interrupted.");
+ }
+ data.add("" + event.getData());
+
+ return CompletableFuture.completedFuture(null);
+ }
+
+ @Override
+ public void close() {
+ System.out.println("Slow subscriber completed");
+ onCompleteLatch.countDown();
+ this.closed = true;
+ }
+ });
+ }
+
+ @GET
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void getServerSentEvents(@Context final SseEventSink eventSink) {
+ broadcaster.register(eventSink);
+ }
+
+ @GET
+ @Path("push/{msg}")
+ public String addMessage(@PathParam("msg") String message) throws InterruptedException {
+ broadcaster.broadcast(sse.newEvent(message));
+ return "Message added.";
+ }
+
+ @GET
+ @Path("close")
+ public String closeMe() {
+ broadcaster.close();
+ return "Closed";
+ }
+
+ @GET
+ @Path("result")
+ public String getResult() {
+ return data.stream().collect(Collectors.joining(","));
+ }
+ }
+
+ @Test
+ public void testBroadcasterKeepsSendingAfterCLose() throws InterruptedException {
+ // push some events to the broadcaster
+ IntStream.range(0, MSG_COUNT).forEach((i) -> {
+ final Response response = target()
+ .path("events/push/{msg}")
+ .resolveTemplate("msg", "msg" + i)
+ .request()
+ .get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ });
+
+ // instruct broadcaster to close
+ final Response response = target().path("events/close").request().get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+
+ // send one more message (should be rejected -> request will fail)
+ final Response badResponse = target()
+ .path("events/push/{msg}")
+ .resolveTemplate("msg", "too-late")
+ .request()
+ .get();
+ Assert.assertNotEquals(Response.Status.OK.getStatusCode(), badResponse.getStatus());
+
+ // wait up to latency * msgcount (+1 as reserve) before the server shuts down
+ Assert.assertTrue(onCompleteLatch.await(SLOW_SUBSCRIBER_LATENCY * (MSG_COUNT + 1), TimeUnit.MILLISECONDS));
+
+ // get data gathered by the slow subsciber
+ String result = target().path("events/result").request().get(String.class);
+ final String[] resultArray = result.split(",");
+
+ // check, that broadcaster sent all the buffered events to the subscriber before completely closing
+ Assert.assertEquals(MSG_COUNT, resultArray.length);
+ for (int i = 0; i < MSG_COUNT; i++) {
+ Assert.assertEquals("msg" + i, resultArray[i]);
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java
new file mode 100644
index 0000000..f272bf9
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.OutboundSseEvent;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseBroadcaster;
+import javax.ws.rs.sse.SseEventSink;
+import javax.ws.rs.sse.SseEventSource;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.client.ClientAsyncExecutor;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ManagedAsyncExecutor;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.spi.ThreadPoolExecutorProvider;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Managed executor service injection and propagation into broadcaster test.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class BroadcasterExecutorTest extends JerseyTest {
+
+ private static final String THREAD_PREFIX = "custom-executor-thread";
+ private static Logger LOGGER = Logger.getLogger(BroadcasterExecutorTest.class.getName());
+
+ private static CountDownLatch closeLatch = new CountDownLatch(1);
+ private static CountDownLatch txLatch = new CountDownLatch(2);
+
+ private static boolean sendThreadOk = false;
+ private static boolean onCompleteThreadOk = false;
+
+ @Path("sse")
+ @Singleton
+ public static class SseResource {
+ private final Sse sse;
+ private SseBroadcaster broadcaster;
+
+ public SseResource(@Context final Sse sse) {
+ this.sse = sse;
+ broadcaster = sse.newBroadcaster();
+ System.out.println("Broadcaster created: " + broadcaster);
+ }
+
+ @GET
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ @Path("events")
+ public void getServerSentEvents(@Context final SseEventSink eventSink, @Context final Sse sse) {
+
+ // TODO JAX-RS 2.1
+ broadcaster.register(new SseEventSink() {
+ @Override
+ public boolean isClosed() {
+ return eventSink.isClosed();
+ }
+
+ @Override
+ public CompletionStage<?> send(OutboundSseEvent event) {
+ final String name = Thread.currentThread().getName();
+ LOGGER.info("onNext called with [" + event + "] from " + name);
+ sendThreadOk = name.startsWith(THREAD_PREFIX);
+ txLatch.countDown();
+ return eventSink.send(event);
+ }
+
+ @Override
+ public void close() {
+ final String name = Thread.currentThread().getName();
+ LOGGER.info("onComplete called from " + name);
+ onCompleteThreadOk = name.startsWith(THREAD_PREFIX);
+ closeLatch.countDown();
+ eventSink.close();
+ }
+ });
+ }
+
+ @Path("push/{msg}")
+ @GET
+ public String pushMessage(@PathParam("msg") final String msg) {
+ broadcaster.broadcast(sse.newEventBuilder().data(msg).build());
+ return "Broadcasting message: " + msg;
+ }
+
+ @Path("close")
+ @GET
+ public String close() {
+ broadcaster.close();
+ return "Closed.";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig rc = new ResourceConfig(SseResource.class);
+ rc.property(ServerProperties.WADL_FEATURE_DISABLE, true);
+ rc.register(new CustomManagedAsyncExecutorProvider());
+ return rc;
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(new CustomClientAsyncExecutor());
+ }
+
+ @ManagedAsyncExecutor
+ private static class CustomManagedAsyncExecutorProvider extends ThreadPoolExecutorProvider {
+ CustomManagedAsyncExecutorProvider() {
+ super("custom-executor-thread");
+ }
+ }
+
+ @ClientAsyncExecutor
+ private static class CustomClientAsyncExecutor extends ThreadPoolExecutorProvider {
+ CustomClientAsyncExecutor() {
+ super("custom-client-executor");
+ }
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ final String[] onEventThreadName = {""};
+ SseEventSource eventSource = SseEventSource
+ .target(target().path("sse/events"))
+ .build();
+
+ eventSource.register((event) -> {
+ LOGGER.info("Event: " + event + " from: " + Thread.currentThread().getName());
+ onEventThreadName[0] = Thread.currentThread().getName();
+ }
+ );
+
+ eventSource.open();
+
+ target().path("sse/push/firstBroadcast").request().get(String.class);
+ target().path("sse/push/secondBroadcast").request().get(String.class);
+ Assert.assertTrue("txLatch time-outed.", txLatch.await(2000, TimeUnit.MILLISECONDS));
+
+ target().path("sse/close").request().get();
+ Assert.assertTrue("closeLatch time-outed.", closeLatch.await(2000, TimeUnit.MILLISECONDS));
+
+ Assert.assertTrue("send either not invoked at all or from wrong thread", sendThreadOk);
+ Assert.assertTrue("onComplete either not invoked at all or from wrong thread", onCompleteThreadOk);
+
+ Assert.assertTrue("Client event called from wrong thread ( " + onEventThreadName[0] + ")",
+ onEventThreadName[0].startsWith("custom-client-executor"));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterTest.java
new file mode 100644
index 0000000..d7e285d
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseBroadcaster;
+import javax.ws.rs.sse.SseEventSink;
+import javax.ws.rs.sse.SseEventSource;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * JAX-RS {@link javax.ws.rs.sse.SseBroadcaster} test.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class BroadcasterTest extends JerseyTest {
+
+ static final CountDownLatch closeLatch = new CountDownLatch(4);
+ static final CountDownLatch txLatch = new CountDownLatch(4);
+ private static boolean isSingleton = false;
+
+ @Path("sse")
+ @Singleton
+ public static class SseResource {
+ private final Sse sse;
+ private SseBroadcaster broadcaster;
+
+ public SseResource(@Context final Sse sse) {
+ this.sse = sse;
+ broadcaster = sse.newBroadcaster();
+ }
+
+ @GET
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ @Path("events")
+ public void getServerSentEvents(@Context final SseEventSink eventSink, @Context final Sse sse) {
+ isSingleton = this.sse == sse;
+ eventSink.send(sse.newEventBuilder().data("Event1").build());
+ eventSink.send(sse.newEventBuilder().data("Event2").build());
+ eventSink.send(sse.newEventBuilder().data("Event3").build());
+ broadcaster.register(eventSink);
+ broadcaster.onClose((subscriber) -> {
+ if (subscriber == eventSink) {
+ closeLatch.countDown();
+ }
+ });
+ txLatch.countDown();
+ }
+
+ @Path("push/{msg}")
+ @GET
+ public String pushMessage(@PathParam("msg") final String msg) {
+ broadcaster.broadcast(sse.newEventBuilder().data(msg).build());
+ txLatch.countDown();
+ return "Broadcasting message: " + msg;
+ }
+
+ @Path("close")
+ @GET
+ public String close() {
+ broadcaster.close();
+ return "Closed.";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig rc = new ResourceConfig(SseResource.class);
+ rc.property(ServerProperties.WADL_FEATURE_DISABLE, true);
+ return rc;
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ SseEventSource eventSourceA = SseEventSource.target(target().path("sse/events")).build();
+ List<String> resultsA1 = new ArrayList<>();
+ List<String> resultsA2 = new ArrayList<>();
+ CountDownLatch a1Latch = new CountDownLatch(5);
+ CountDownLatch a2Latch = new CountDownLatch(5);
+ eventSourceA.register((event) -> {
+ resultsA1.add(event.readData());
+ a1Latch.countDown();
+ });
+ eventSourceA.register((event) -> {
+ resultsA2.add(event.readData());
+ a2Latch.countDown();
+ });
+ eventSourceA.open();
+
+ target().path("sse/push/firstBroadcast").request().get(String.class);
+
+
+ SseEventSource eventSourceB = SseEventSource.target(target().path("sse/events")).build();
+ List<String> resultsB1 = new ArrayList<>();
+ List<String> resultsB2 = new ArrayList<>();
+ CountDownLatch b1Latch = new CountDownLatch(4);
+ CountDownLatch b2Latch = new CountDownLatch(4);
+ eventSourceB.register((event) -> {
+ resultsB1.add(event.readData());
+ b1Latch.countDown();
+ });
+ eventSourceB.register((event) -> {
+ resultsB2.add(event.readData());
+ b2Latch.countDown();
+ });
+ eventSourceB.open();
+
+ target().path("sse/push/secondBroadcast").request().get(String.class);
+
+ Assert.assertTrue("Waiting for resultsA1 to be complete failed.",
+ a1Latch.await(3000, TimeUnit.MILLISECONDS));
+ Assert.assertTrue("Waiting for resultsA2 to be complete failed.",
+ a2Latch.await(3000, TimeUnit.MILLISECONDS));
+
+ Assert.assertTrue("Waiting for resultsB1 to be complete failed.",
+ b1Latch.await(3000, TimeUnit.MILLISECONDS));
+ Assert.assertTrue("Waiting for resultsB2 to be complete failed.",
+ b2Latch.await(3000, TimeUnit.MILLISECONDS));
+
+ Assert.assertTrue(txLatch.await(5000, TimeUnit.MILLISECONDS));
+
+ // Event1, Event2, Event3, firstBroadcast, secondBroadcast
+ Assert.assertEquals("resultsA1 does not contain 5 elements.", 5, resultsA1.size());
+ Assert.assertEquals("resultsA2 does not contain 5 elements.", 5, resultsA2.size());
+ Assert.assertTrue("resultsA1 does not contain expected data",
+ resultsA1.get(0).equals("Event1")
+ && resultsA1.get(1).equals("Event2")
+ && resultsA1.get(2).equals("Event3")
+ && resultsA1.get(3).equals("firstBroadcast")
+ && resultsA1.get(4).equals("secondBroadcast"));
+
+ Assert.assertTrue("resultsA2 does not contain expected data",
+ resultsA2.get(0).equals("Event1")
+ && resultsA2.get(1).equals("Event2")
+ && resultsA2.get(2).equals("Event3")
+ && resultsA2.get(3).equals("firstBroadcast")
+ && resultsA2.get(4).equals("secondBroadcast"));
+
+ Assert.assertEquals("resultsB1 does not contain 4 elements.", 4, resultsB1.size());
+ Assert.assertEquals("resultsB2 does not contain 4 elements.", 4, resultsB2.size());
+ Assert.assertTrue("resultsB1 does not contain expected data",
+ resultsB1.get(0).equals("Event1")
+ && resultsB1.get(1).equals("Event2")
+ && resultsB1.get(2).equals("Event3")
+ && resultsB1.get(3).equals("secondBroadcast"));
+
+ Assert.assertTrue("resultsB2 does not contain expected data",
+ resultsB2.get(0).equals("Event1")
+ && resultsB2.get(1).equals("Event2")
+ && resultsB2.get(2).equals("Event3")
+ && resultsB2.get(3).equals("secondBroadcast"));
+ target().path("sse/close").request().get();
+ Assert.assertTrue(closeLatch.await(3000, TimeUnit.MILLISECONDS));
+ Assert.assertTrue("Sse instances injected into resource and constructor differ. Sse should have been injected"
+ + "as a singleton", isSingleton);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventOutputTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventOutputTest.java
new file mode 100644
index 0000000..0f09d26
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventOutputTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.io.IOException;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.media.sse.EventInput;
+import org.glassfish.jersey.media.sse.EventListener;
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Event output tests.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class EventOutputTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SseTestResource.class, SseFeature.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(SseFeature.class);
+ }
+
+ /**
+ * SSE Test resource.
+ */
+ @Path("test")
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public static class SseTestResource {
+
+ @GET
+ @Path("single")
+ public EventOutput getSingleEvent() {
+ final EventOutput output = new EventOutput();
+ try {
+ return output;
+ } finally {
+ new Thread() {
+ public void run() {
+ try {
+ output.write(new OutboundEvent.Builder().data(String.class, "single").build());
+ output.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+ }.start();
+ }
+ }
+
+ @GET
+ @Path("closed-single")
+ public EventOutput getClosedSingleEvent() throws IOException {
+ final EventOutput output = new EventOutput();
+ output.write(new OutboundEvent.Builder().data(String.class, "closed").build());
+ output.close();
+ return output;
+ }
+
+ @GET
+ @Path("closed-empty")
+ public EventOutput getClosedEmpty() throws IOException {
+ final EventOutput output = new EventOutput();
+ output.close();
+ return output;
+ }
+
+ @GET
+ @Path("charset")
+ @Produces("text/event-stream;charset=utf-8")
+ public EventOutput getSseWithCharset() throws IOException {
+ final EventOutput output = new EventOutput();
+ output.write(new OutboundEvent.Builder().data(String.class, "charset").build());
+ output.close();
+ return output;
+ }
+
+ @GET
+ @Path("comments-only")
+ public EventOutput getCommentsOnlyStream() throws IOException {
+ final EventOutput output = new EventOutput();
+ output.write(new OutboundEvent.Builder().comment("No comment #1").build());
+ output.write(new OutboundEvent.Builder().comment("No comment #2").build());
+ output.close();
+ return output;
+ }
+ }
+
+ @Test
+ public void testReadSseEventAsPlainString() throws Exception {
+ final Response r = target().path("test/single").request().get(Response.class);
+ assertThat(r.readEntity(String.class), containsString("single"));
+ }
+
+ /**
+ * Reproducer for JERSEY-2912: Sending and receiving comments-only events.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testReadCommentsOnlySseEvents() throws Exception {
+ ClientConfig clientConfig = new ClientConfig();
+ clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 15000);
+ clientConfig.property(ClientProperties.READ_TIMEOUT, 0);
+ clientConfig.property(ClientProperties.ASYNC_THREADPOOL_SIZE, 8);
+ clientConfig.connectorProvider(new GrizzlyConnectorProvider());
+ Client client = ClientBuilder.newBuilder().withConfig(clientConfig).build();
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ final Queue<String> eventComments = new ArrayBlockingQueue<>(2);
+ WebTarget single = client.target(getBaseUri()).path("test/comments-only");
+ EventSource es = EventSource.target(single).build();
+ es.register(new EventListener() {
+ @Override
+ public void onEvent(InboundEvent inboundEvent) {
+ eventComments.add(inboundEvent.getComment());
+ latch.countDown();
+ }
+ });
+
+ boolean latchTimedOut;
+ boolean closeTimedOut;
+ try {
+ es.open();
+ latchTimedOut = latch.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ } finally {
+ closeTimedOut = es.close(5, TimeUnit.SECONDS);
+ }
+
+ assertEquals("Unexpected event count", 2, eventComments.size());
+ for (int i = 1; i <= 2; i++) {
+ assertEquals("Unexpected comment data on event #" + i, "No comment #" + i, eventComments.poll());
+ }
+ assertTrue("Event latch has timed out", latchTimedOut);
+ assertTrue("EventSource.close() has timed out", closeTimedOut);
+ }
+
+ @Test
+ public void testReadFromClosedOutput() throws Exception {
+ /**
+ * Need to disable HTTP Keep-Alive to prevent this test from hanging in HttpURLConnection
+ * due to an attempt to read from a stale, out-of-sync connection closed by the server.
+ * Thus setting the "Connection: close" HTTP header on all requests.
+ */
+ Response r;
+ r = target().path("test/closed-empty").request().header("Connection", "close").get();
+ assertTrue(r.readEntity(String.class).isEmpty());
+
+ r = target().path("test/closed-single").request().header("Connection", "close").get();
+ assertTrue(r.readEntity(String.class).contains("closed"));
+
+ //
+
+ EventInput input;
+ input = target().path("test/closed-single").request().header("Connection", "close").get(EventInput.class);
+ assertEquals("closed", input.read().readData());
+ assertEquals(null, input.read());
+ assertTrue(input.isClosed());
+
+ input = target().path("test/closed-empty").request().header("Connection", "close").get(EventInput.class);
+ assertEquals(null, input.read());
+ assertTrue(input.isClosed());
+ }
+
+ @Test
+ public void testSseContentTypeWithCharset() {
+ /**
+ * Need to disable HTTP Keep-Alive to prevent this test from hanging in HttpURLConnection
+ * due to an attempt to read from a stale, out-of-sync connection closed by the server.
+ * Thus setting the "Connection: close" HTTP header on all requests.
+ */
+ Response r;
+ r = target().path("test/charset").request().header("Connection", "close").get();
+ assertTrue(r.getMediaType().getParameters().get("charset").equalsIgnoreCase("utf-8"));
+ final EventInput eventInput = r.readEntity(EventInput.class);
+ String eventData = eventInput.read().readData();
+ assertEquals("charset", eventData);
+ eventInput.close();
+ }
+
+ @Test
+ public void testGrizzlyConnectorWithEventSource() throws InterruptedException {
+ ClientConfig clientConfig = new ClientConfig();
+ clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 15000);
+ clientConfig.property(ClientProperties.READ_TIMEOUT, 0);
+ clientConfig.property(ClientProperties.ASYNC_THREADPOOL_SIZE, 8);
+ clientConfig.connectorProvider(new GrizzlyConnectorProvider());
+ Client client = ClientBuilder.newBuilder().withConfig(clientConfig).build();
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<String> eventData = new AtomicReference<String>();
+ final AtomicInteger counter = new AtomicInteger(0);
+ WebTarget single = client.target(getBaseUri()).path("test/single");
+ EventSource es = EventSource.target(single).build();
+ es.register(new EventListener() {
+ @Override
+ public void onEvent(InboundEvent inboundEvent) {
+ final int i = counter.incrementAndGet();
+ if (i == 1) {
+ eventData.set(inboundEvent.readData());
+ }
+ latch.countDown();
+ }
+ });
+
+ boolean latchTimedOut;
+ boolean closeTimedOut;
+ try {
+ es.open();
+ latchTimedOut = latch.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ } finally {
+ closeTimedOut = es.close(5, TimeUnit.SECONDS);
+ }
+
+ assertEquals("Unexpected event count", 1, counter.get());
+ assertEquals("Unexpected event data", "single", eventData.get());
+ assertTrue("Event latch has timed out", latchTimedOut);
+ assertTrue("EventSource.close() has timed out", closeTimedOut);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventSourceWithNamedEventsTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventSourceWithNamedEventsTest.java
new file mode 100644
index 0000000..28f9edf
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/EventSourceWithNamedEventsTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.media.sse.EventListener;
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests handling of SSEs with name defined in {@link EventSource}.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class EventSourceWithNamedEventsTest extends JerseyTest {
+
+ public static final String SSE_NAME = "message-to-client";
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(SseResource.class, SseFeature.class);
+ return resourceConfig;
+ }
+
+ public static final int MSG_COUNT = 10;
+ private static final CountDownLatch latch = new CountDownLatch(MSG_COUNT);
+
+ @Path("events")
+ @Singleton
+ public static class SseResource {
+
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput getServerSentEvents() {
+ final EventOutput eventOutput = new EventOutput();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ int i = 0;
+ while (latch.getCount() > 0) {
+
+ // send message with name "message-to-client" -> should be read by the client
+ eventOutput.write(new OutboundEvent.Builder()
+ .name("message-to-client")
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(Integer.class, i)
+ .build());
+
+ // send another event with name "foo" -> should be ignored by the client
+ eventOutput.write(new OutboundEvent.Builder()
+ .name("foo")
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(String.class, "bar")
+ .build());
+
+ // send another un-mamed event -> should be ignored by the client
+ eventOutput.write(new OutboundEvent.Builder()
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(String.class, "baz")
+ .build());
+ latch.countDown();
+ i++;
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("Error when writing the event.", e);
+ } finally {
+ try {
+ eventOutput.close();
+ } catch (IOException ioClose) {
+ throw new RuntimeException("Error when closing the event output.", ioClose);
+ }
+ }
+ }
+ }).start();
+ return eventOutput;
+ }
+ }
+
+
+ @Test
+ public void testWithEventSource() throws IOException, NoSuchAlgorithmException, InterruptedException {
+ final WebTarget endpoint = target().register(SseFeature.class).path("events");
+ EventSource eventSource = EventSource.target(endpoint).build();
+ final CountDownLatch count = new CountDownLatch(MSG_COUNT);
+
+ final EventListener listener = new EventListener() {
+ @Override
+ public void onEvent(InboundEvent inboundEvent) {
+ try {
+ final Integer data = inboundEvent.readData(Integer.class);
+ System.out.println(inboundEvent.getName() + "; " + data);
+ Assert.assertEquals(SSE_NAME, inboundEvent.getName());
+ Assert.assertEquals(MSG_COUNT - count.getCount(), data.intValue());
+ count.countDown();
+ } catch (ProcessingException ex) {
+ throw new RuntimeException("Error when deserializing of data.", ex);
+ }
+ }
+ };
+ eventSource.register(listener, "message-to-client");
+ eventSource.open();
+ final boolean sent = latch.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertTrue("Awaiting for SSE message has timeout. Not all message were sent.", sent);
+ final boolean handled = count.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertTrue("Awaiting for SSE message has timeout. Not all message were handled by the listener.", handled);
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/GenericEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/GenericEntityTest.java
new file mode 100644
index 0000000..cbd3e9b
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/GenericEntityTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import javafx.util.Pair;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseEventSink;
+import javax.ws.rs.sse.SseEventSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+public class GenericEntityTest extends JerseyTest {
+ private static final int BUFFER_SIZE = 20;
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(GenericEntityTest.SSEGenericEntityResource.class, ListPairMBRW.class, PairMBRW.class);
+ }
+
+ @Test
+ public void testGenericString() throws InterruptedException {
+ WebTarget sseTarget = target("genericentityresource/string");
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ MessageLatch<String> messageLatch = new MessageLatch<>(countDownLatch);
+ try (SseEventSource source = SseEventSource.target(sseTarget).build()) {
+ source.register(event -> messageLatch.consume(event.readData()));
+ source.open();
+ assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
+ assertEquals("Cindy", messageLatch.data().get(0));
+ }
+ }
+
+ @Test
+ public void testGenericPair() throws InterruptedException {
+ WebTarget sseTarget = target("genericentityresource/pair").register(PairMBRW.class);
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ MessageLatch<Pair<String, Integer>> messageLatch = new MessageLatch<>(countDownLatch);
+ try (SseEventSource source = SseEventSource.target(sseTarget).build()) {
+ source.register(event -> messageLatch.consume(event.readData(Pair.class)));
+ source.open();
+ assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
+ Pair<String, Integer> pair = messageLatch.data().get(0);
+ assertEquals("Cindy", pair.getKey());
+ assertEquals(30, pair.getValue().intValue());
+ }
+ }
+
+ @Test
+ public void testGenericList() throws InterruptedException {
+ WebTarget sseTarget = target("genericentityresource/list").register(ListPairMBRW.class);
+ CountDownLatch countDownLatch = new CountDownLatch(2);
+ MessageLatch<Pair<String, Integer>> messageLatch = new MessageLatch<>(countDownLatch);
+ try (SseEventSource source = SseEventSource.target(sseTarget).build()) {
+ source.register(event -> messageLatch.consume((List<Pair<String, Integer>>) event.readData(List.class)));
+ source.open();
+ assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
+ Pair<String, Integer> cindy = messageLatch.data().get(0);
+ Pair<String, Integer> jack = messageLatch.data().get(1);
+ assertEquals("Cindy", cindy.getKey());
+ assertEquals(30, cindy.getValue().intValue());
+ assertEquals("Jack", jack.getKey());
+ assertEquals(32, jack.getValue().intValue());
+ }
+ }
+
+ @Singleton
+ @Path("genericentityresource")
+ public static class SSEGenericEntityResource {
+ @GET
+ @Path("string")
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void sendString(@Context SseEventSink sink, @Context Sse sse) {
+ GenericEntity<String> ges = new GenericEntity<String>("Cindy") {
+ };
+ try (SseEventSink s = sink) {
+ s.send(sse.newEventBuilder().data(ges).build());
+ }
+ }
+
+ @GET
+ @Path("pair")
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void sendPair(@Context SseEventSink sink, @Context Sse sse) {
+ Pair<String, Integer> person = new Pair<>("Cindy", 30);
+ GenericEntity<Pair<String, Integer>> entity = new GenericEntity<Pair<String, Integer>>(person) {
+ };
+ try (SseEventSink s = sink) {
+ s.send(sse.newEventBuilder().data(entity).build());
+ }
+ }
+
+ @GET
+ @Path("list")
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void sendList(@Context SseEventSink sink, @Context Sse sse) {
+ Pair<String, Integer> person1 = new Pair<>("Cindy", 30);
+ Pair<String, Integer> person2 = new Pair<>("Jack", 32);
+ List<Pair<String, Integer>> people = new LinkedList<>();
+ people.add(person1);
+ people.add(person2);
+ GenericEntity<List<Pair<String, Integer>>> entity = new GenericEntity<List<Pair<String, Integer>>>(people) {
+ };
+ try (SseEventSink s = sink) {
+ s.send(sse.newEventBuilder().data(entity).build());
+ }
+ }
+ }
+
+ private static class PairMBRW implements
+ MessageBodyWriter<Pair<String, Integer>>, MessageBodyReader<Pair<String, Integer>> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == Pair.class;
+ }
+
+ @Override
+ public Pair<String, Integer> readFrom(Class<Pair<String, Integer>> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ byte[] buffer = new byte[GenericEntityTest.BUFFER_SIZE];
+ entityStream.read(buffer);
+ return readFrom(new String(buffer, Charset.defaultCharset()).trim());
+ }
+
+ static Pair<String, Integer> readFrom(String from) {
+ String[] split = from.split(",", 2);
+ return new Pair<String, Integer>(split[0], Integer.parseInt(split[1]));
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == Pair.class;
+ }
+
+ @Override
+ public void writeTo(Pair<String, Integer> stringIntegerPair, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ writeTo(stringIntegerPair, entityStream);
+ }
+
+ static void writeTo(Pair<String, Integer> stringIntegerPair, OutputStream entityStream) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ sb.append(stringIntegerPair.getKey()).append(",").append(stringIntegerPair.getValue());
+ entityStream.write(sb.toString().getBytes(Charset.defaultCharset()));
+ }
+ }
+
+ private static class ListPairMBRW implements MessageBodyWriter<List<Pair<String, Integer>>>,
+ MessageBodyReader<List<Pair<String, Integer>>> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == List.class;
+ }
+
+ @Override
+ public List<Pair<String, Integer>> readFrom(Class<List<Pair<String, Integer>>> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream)
+ throws IOException, WebApplicationException {
+ List<Pair<String, Integer>> list = new LinkedList<>();
+ byte[] buffer = new byte[20];
+ entityStream.read(buffer);
+ StringTokenizer st = new StringTokenizer(new String(buffer, Charset.defaultCharset()).trim(), ";", false);
+ while (st.hasMoreTokens()) {
+ list.add(PairMBRW.readFrom(st.nextToken()));
+ }
+ return list;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == List.class;
+ }
+
+ @Override
+ public void writeTo(List<Pair<String, Integer>> pairs, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ for (Pair<String, Integer> pair : pairs) {
+ PairMBRW.writeTo(pair, entityStream);
+ entityStream.write(";".getBytes());
+ }
+ }
+ }
+
+ private static class MessageLatch<T> {
+ private CountDownLatch countDownLatch;
+ private List<T> data = new LinkedList<>();
+
+ private MessageLatch(CountDownLatch countDownLatch) {
+ this.countDownLatch = countDownLatch;
+ }
+
+ private void consume(List<T> list) {
+ for (T o : list) {
+ data.add(o);
+ countDownLatch.countDown();
+ }
+ }
+
+ private void consume(T o) {
+ data.add(o);
+ countDownLatch.countDown();
+ }
+
+ private List<T> data() {
+ return data;
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseCustomEventImplTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseCustomEventImplTest.java
new file mode 100644
index 0000000..ec58d06
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseCustomEventImplTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.InboundSseEvent;
+import javax.ws.rs.sse.OutboundSseEvent;
+import javax.ws.rs.sse.SseEventSink;
+import javax.ws.rs.sse.SseEventSource;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.media.sse.EventListener;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test that {@link org.glassfish.jersey.media.sse.OutboundEventWriter} works with custom
+ * {@link javax.ws.rs.sse.OutboundSseEvent} implementation.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class SseCustomEventImplTest extends JerseyTest {
+
+ private static final String SSE_EVENT_NAME = "custom-message";
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SseResource.class);
+ }
+
+ @Path("events")
+ @Singleton
+ public static class SseResource {
+
+ @GET
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void getServerSentEvents(@Context final SseEventSink eventSink) {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.submit(() -> {
+ eventSink.send(new MyOutboundEvent("foo"));
+ eventSink.send(new MyOutboundEvent("bar"));
+ eventSink.send(new MyOutboundEvent("baz"));
+ });
+ }
+ }
+
+ @Test
+ public void testWithJaxRsAPI() {
+ final WebTarget endpoint = target().path("events");
+ final List<InboundSseEvent> results = new ArrayList<>();
+ try (final SseEventSource eventSource = SseEventSource.target(endpoint).build()) {
+ final CountDownLatch receivedLatch = new CountDownLatch(3);
+ eventSource.register((event) -> {
+ results.add(event);
+ receivedLatch.countDown();
+ });
+
+ eventSource.open();
+ final boolean allReceived = receivedLatch.await(5000, TimeUnit.MILLISECONDS);
+ Assert.assertTrue(allReceived);
+ Assert.assertEquals(3, results.size());
+ Assert.assertEquals("foo", results.get(0).readData());
+ Assert.assertEquals("bar", results.get(1).readData());
+ Assert.assertEquals("baz", results.get(2).readData());
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testWithJerseyAPI() throws InterruptedException {
+ final WebTarget endpoint = target().path("events");
+ final EventSource eventSource = EventSource.target(endpoint).build();
+ final CountDownLatch receiveLatch = new CountDownLatch(3);
+
+ final List<String> results = new ArrayList<>();
+ final EventListener listener = inboundEvent -> {
+ try {
+ results.add(inboundEvent.readData());
+ receiveLatch.countDown();
+ Assert.assertEquals(SSE_EVENT_NAME, inboundEvent.getName());
+ } catch (ProcessingException ex) {
+ throw new RuntimeException("Error when deserializing of data.", ex);
+ }
+ };
+ eventSource.register(listener, SSE_EVENT_NAME);
+ eventSource.open();
+ Assert.assertTrue(receiveLatch.await(5000, TimeUnit.MILLISECONDS));
+ Assert.assertEquals(3, results.size());
+ Assert.assertEquals("foo", results.get(0));
+ Assert.assertEquals("bar", results.get(1));
+ Assert.assertEquals("baz", results.get(2));
+ }
+
+ static class MyOutboundEvent implements OutboundSseEvent {
+
+ private String data;
+
+ public MyOutboundEvent(String data) {
+ this.data = data;
+ }
+
+ @Override
+ public Class<?> getType() {
+ return String.class;
+ }
+
+ @Override
+ public Type getGenericType() {
+ return String.class;
+ }
+
+ @Override
+ public MediaType getMediaType() {
+ return MediaType.TEXT_PLAIN_TYPE;
+ }
+
+ @Override
+ public String getData() {
+ return data;
+ }
+
+ @Override
+ public String getId() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return SSE_EVENT_NAME;
+ }
+
+ @Override
+ public String getComment() {
+ return "";
+ }
+
+ @Override
+ public long getReconnectDelay() {
+ return 0;
+ }
+
+ @Override
+ public boolean isReconnectDelaySet() {
+ return false;
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseEventSinkToEventSourceTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseEventSinkToEventSourceTest.java
new file mode 100644
index 0000000..4bc9af3
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/SseEventSinkToEventSourceTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.InboundSseEvent;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseEventSink;
+import javax.ws.rs.sse.SseEventSource;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.media.sse.EventListener;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * JAX-RS {@link SseEventSource} and {@link SseEventSink} test.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class SseEventSinkToEventSourceTest extends JerseyTest {
+
+ private static final String INTEGER_SSE_NAME = "integer-message";
+ private static final Logger LOGGER = Logger.getLogger(SseEventSinkToEventSourceTest.class.getName());
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SseResource.class);
+ }
+
+ private static final int MSG_COUNT = 10;
+ private static volatile CountDownLatch transmitLatch;
+
+ @Path("events")
+ @Singleton
+ public static class SseResource {
+
+ @GET
+ @Produces(MediaType.SERVER_SENT_EVENTS)
+ public void getServerSentEvents(@Context final SseEventSink eventSink, @Context final Sse sse) {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.submit(() -> {
+ int i = 0;
+ while (transmitLatch.getCount() > 0) {
+ eventSink.send(sse.newEventBuilder()
+ .name(INTEGER_SSE_NAME)
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(Integer.class, i)
+ .build());
+
+ // send another event with name "foo" -> should be ignored by the client
+ eventSink.send(sse.newEventBuilder()
+ .name("foo")
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(String.class, "bar")
+ .build());
+
+ // send another unnamed event -> should be ignored by the client
+ eventSink.send(sse.newEventBuilder()
+ .mediaType(MediaType.TEXT_PLAIN_TYPE)
+ .data(String.class, "baz")
+ .build());
+ transmitLatch.countDown();
+ i++;
+ }
+ });
+ }
+ }
+
+ @Test
+ public void testWithSimpleSubscriber() {
+ transmitLatch = new CountDownLatch(MSG_COUNT);
+ final WebTarget endpoint = target().path("events");
+ final List<InboundSseEvent> results = new ArrayList<>();
+ try (final SseEventSource eventSource = SseEventSource.target(endpoint).build()) {
+ final CountDownLatch receivedLatch = new CountDownLatch(3 * MSG_COUNT);
+ eventSource.register((event) -> {
+ results.add(event);
+ receivedLatch.countDown();
+ });
+
+ eventSource.open();
+ final boolean allTransmitted = transmitLatch.await(5000, TimeUnit.MILLISECONDS);
+ final boolean allReceived = receivedLatch.await(5000, TimeUnit.MILLISECONDS);
+ Assert.assertTrue(allTransmitted);
+ Assert.assertTrue(allReceived);
+ Assert.assertEquals(30, results.size());
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testWithJerseyApi() throws InterruptedException {
+ final WebTarget endpoint = target().path("events");
+ final EventSource eventSource = EventSource.target(endpoint).build();
+ transmitLatch = new CountDownLatch(MSG_COUNT);
+ final CountDownLatch receiveLatch = new CountDownLatch(MSG_COUNT);
+
+ final List<Integer> results = new ArrayList<>();
+ final EventListener listener = inboundEvent -> {
+ try {
+ results.add(inboundEvent.readData(Integer.class));
+ receiveLatch.countDown();
+ Assert.assertEquals(INTEGER_SSE_NAME, inboundEvent.getName());
+ } catch (ProcessingException ex) {
+ throw new RuntimeException("Error when deserializing of data.", ex);
+ }
+ };
+ eventSource.register(listener, INTEGER_SSE_NAME);
+ eventSource.open();
+ Assert.assertTrue(transmitLatch.await(5000, TimeUnit.MILLISECONDS));
+ Assert.assertTrue(receiveLatch.await(5000, TimeUnit.MILLISECONDS));
+ Assert.assertEquals(10, results.size());
+ }
+
+
+ @Test
+ public void testWithEventSource() throws InterruptedException {
+ transmitLatch = new CountDownLatch(2 * MSG_COUNT);
+ final WebTarget endpoint = target().path("events");
+ final SseEventSource eventSource = SseEventSource.target(endpoint).build();
+
+ final CountDownLatch count1 = new CountDownLatch(3 * MSG_COUNT);
+ final CountDownLatch count2 = new CountDownLatch(3 * MSG_COUNT);
+
+ eventSource.register(new InboundHandler("consumer1", count1));
+ eventSource.register(new InboundHandler("consumer2", count2));
+
+ eventSource.open();
+ final boolean sent = transmitLatch.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertTrue("Awaiting for SSE message has timeout. Not all message were sent.", sent);
+
+ final boolean handled2 = count2.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertTrue(
+ "Awaiting for SSE message has timeout. Not all message were handled by eventSource2.", handled2);
+
+ final boolean handled1 = count1.await(5 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+ Assert.assertTrue(
+ "Awaiting for SSE message has timeout. Not all message were handled by eventSource1.", handled1);
+
+ }
+
+ private class InboundHandler implements Consumer<InboundSseEvent> {
+ private final CountDownLatch latch;
+ private final String name;
+
+ InboundHandler(final String name, final CountDownLatch latch) {
+ this.latch = latch;
+ this.name = name;
+ }
+
+ @Override
+ public void accept(final InboundSseEvent inboundSseEvent) {
+ try {
+ if (INTEGER_SSE_NAME.equals(inboundSseEvent.getName())) {
+ final Integer data = inboundSseEvent.readData(Integer.class);
+ LOGGER.info(String.format("[%s] Integer data received: [id=%s name=%s comment=%s reconnectDelay=%d value=%d]",
+ name,
+ inboundSseEvent.getId(),
+ inboundSseEvent.getName(), inboundSseEvent.getComment(), inboundSseEvent.getReconnectDelay(), data));
+ } else {
+ final String data = inboundSseEvent.readData();
+ LOGGER.info(String.format("[%s] String data received: [id=%s name=%s comment=%s reconnectDelay=%d value=%s]",
+ name,
+ inboundSseEvent.getId(),
+ inboundSseEvent.getName(), inboundSseEvent.getComment(), inboundSseEvent.getReconnectDelay(), data));
+ }
+ latch.countDown();
+ } catch (final ProcessingException ex) {
+ throw new RuntimeException("Error when deserializing the data.", ex);
+ }
+ }
+ }
+}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/Jersey_yellow.png b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/Jersey_yellow.png
new file mode 100644
index 0000000..ec74cd2
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/Jersey_yellow.png
Binary files differ
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/duke_rocket.gif b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/duke_rocket.gif
new file mode 100644
index 0000000..420304f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/duke_rocket.gif
Binary files differ
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/multipart-testcase.txt b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/multipart-testcase.txt
new file mode 100644
index 0000000..e4557cc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/multipart-testcase.txt
@@ -0,0 +1,11 @@
+-----------------------------7dc941520888
+Content-Disposition: form-data; name="text"
+
+bhhklb
+-----------------------------7dc941520888
+Content-Disposition: form-data; name="file"; filename="C:\java\projects\multipart-testcase\pom.xml"
+Content-Type: text/xml
+
+<project/>
+
+-----------------------------7dc941520888--
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/xxe.txt b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/xxe.txt
new file mode 100644
index 0000000..fad27b5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/xxe.txt
@@ -0,0 +1 @@
+COMPROMISED
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList.json
new file mode 100644
index 0000000..e91caf6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"Dog","name":"Fifi"},{"@type":"Cat","name":"Daisy","nickName":null}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..e91caf6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"Dog","name":"Fifi"},{"@type":"Cat","name":"Daisy","nickName":null}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..dfb3702
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..dfb3702
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..892c41c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"},{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..b654a20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"a1":null,"a2":null,"list":[],"b":{"uri":null,"s1":null,"i":null,"j":null}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..b654a20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"a1":null,"a2":null,"list":[],"b":{"uri":null,"s1":null,"i":null,"j":null}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..892c41c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"},{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..440cf2e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{"nullOnly":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..440cf2e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{"nullOnly":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..10a199b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"emptyBean":null,"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..10a199b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyBean":null,"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..75b2873
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"objects":[{"@type":"ColorHolder","colors":["RED","BLUE"]},{"@type":"ColorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..75b2873
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"objects":[{"@type":"ColorHolder","colors":["RED","BLUE"]},{"@type":"ColorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse.json
new file mode 100644
index 0000000..619148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..619148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..a23e9d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"attr":"value","a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..a23e9d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"attr":"value","a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person.json
new file mode 100644
index 0000000..f3dc062
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","children":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..f3dc062
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","children":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList.json
new file mode 100644
index 0000000..e3f81df
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","name":"Daisy","nickName":null}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList_MOXy.json
new file mode 100644
index 0000000..e3f81df
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PojoAnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","name":"Daisy","nickName":null}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..5868341
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..5868341
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel.json
new file mode 100644
index 0000000..7ffadb3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..7ffadb3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User.json
new file mode 100644
index 0000000..5032ee5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User.json
@@ -0,0 +1 @@
+{"name":"Grotefend","userid":"1621"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable.json
new file mode 100644
index 0000000..7c9561f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"name":"Grotefend","userid":"1621"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..7c9561f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"name":"Grotefend","userid":"1621"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User_MOXy.json
new file mode 100644
index 0000000..5032ee5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/Jackson1JsonTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"name":"Grotefend","userid":"1621"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList.json
new file mode 100644
index 0000000..3da277e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"Dog","name":"Fifi"},{"@type":"Cat","nickName":null,"name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..368ad25
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"Dog","name":"Fifi"},{"@type":"Cat","name":"Daisy","nickName":null}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..f364f00
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"prop":"testProp","cats":[{"nickName":"Kitty","name":"Foo"},{"nickName":"Puss","name":"Bar"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..d9dc02f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..892c41c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"},{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..b654a20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"a1":null,"a2":null,"list":[],"b":{"uri":null,"s1":null,"i":null,"j":null}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..01a7674
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"a1":null,"a2":null,"filler1":null,"list":[],"filler2":null,"b":{"uri":null,"s1":null,"i":null,"j":null}}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..892c41c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"},{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..440cf2e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{"nullOnly":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..440cf2e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{"nullOnly":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..10a199b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"emptyBean":null,"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..10a199b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyBean":null,"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..75b2873
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"objects":[{"@type":"ColorHolder","colors":["RED","BLUE"]},{"@type":"ColorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..75b2873
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"objects":[{"@type":"ColorHolder","colors":["RED","BLUE"]},{"@type":"ColorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse.json
new file mode 100644
index 0000000..619148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..619148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..a23e9d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"attr":"value","a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..a23e9d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"attr":"value","a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person.json
new file mode 100644
index 0000000..466eda7
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","child":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..b96eb26
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","child":[{"name":"Jill Schmo","child":null},{"name":"Jack Schmo","child":null}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList.json
new file mode 100644
index 0000000..2a49520
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","nickName":null,"name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList_MOXy.json
new file mode 100644
index 0000000..2387979
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PojoAnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","name":"Daisy","nickName":null}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..5868341
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..5868341
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","s1":"hi there","i":312,"j":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel.json
new file mode 100644
index 0000000..7ffadb3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..92e0027
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false,"children":null}}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User.json
new file mode 100644
index 0000000..a1b91b6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User.json
@@ -0,0 +1 @@
+{"userid":"1621","name":"Grotefend"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable.json
new file mode 100644
index 0000000..2652195
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"userid":"1621","name":"Grotefend"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..3c38fcb
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"name":"Grotefend","userid":"1621"}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User_MOXy.json
new file mode 100644
index 0000000..a517e84
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JacksonJsonTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"name":"Grotefend","userid":"1621"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList.json
new file mode 100644
index 0000000..97dda24
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animalList":{"animals":[{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"dog","name":{"$":"Fifi"}},{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"cat","name":{"$":"Daisy"}}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..97dda24
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animalList":{"animals":[{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"dog","name":{"$":"Fifi"}},{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"cat","name":{"$":"Daisy"}}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..b4d148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"anotherArrayTestBean":{"cats":[{"name":{"$":"Foo"},"nickName":{"$":"Kitty"}},{"name":{"$":"Bar"},"nickName":{"$":"Puss"}}],"prop":{"$":"testProp"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..b4d148e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"anotherArrayTestBean":{"cats":[{"name":{"$":"Foo"},"nickName":{"$":"Kitty"}},{"name":{"$":"Bar"},"nickName":{"$":"Puss"}}],"prop":{"$":"testProp"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..4b41cc9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"parent":{"@attr":"aval","$":"pval"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..4b41cc9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"parent":{"@attr":"aval","$":"pval"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..32bb5fe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes":{"@a2":"31415926","@a1":"hello dolly","filler1":{"$":"111"},"list":[{"@j":"bumper","@i":"312","@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","s1":{"$":"hi there"}},{"@j":"bumper","@i":"312","@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","s1":{"$":"hi there"}}],"filler2":{"$":"222"},"b":{"@j":"bumper","@i":"312","@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","s1":{"$":"hi there"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..ff8b049
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes2":{"@a2":"31415926","@a1":"hello dolly","filler1":{"$":"111"},"list":[{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"},{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}],"filler2":{"$":"222"},"b":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..b9e68ae
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes2":{"@a1":"hello dolly","@a2":"31415926","filler1":{"$":"111"},"list":[{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"},{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}],"filler2":{"$":"222"},"b":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..9f6d6ca
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes3":{"b":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"},"c":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..9f6d6ca
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes3":{"b":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"},"c":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..3199988
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes4":{"b":{}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..3199988
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes4":{"b":{}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..b1aac1c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes":{"@a1":"hello dolly","@a2":"31415926","filler1":{"$":"111"},"list":[{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","@i":"312","@j":"bumper","s1":{"$":"hi there"}},{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","@i":"312","@j":"bumper","s1":{"$":"hi there"}}],"filler2":{"$":"222"},"b":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","@i":"312","@j":"bumper","s1":{"$":"hi there"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..87fb1f6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{"emptyElementBean":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..87fb1f6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyElementBean":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..6c111ff
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"emptyElementContainingBean":{"c":{"$":"foo"},"d":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..6c111ff
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyElementContainingBean":{"c":{"$":"foo"},"d":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..e3c9100
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"encodedContentBean":{"one":{"$":"\tone\n\tbig"},"two":{"$":"hafČ"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..e3c9100
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"encodedContentBean":{"one":{"$":"\tone\n\tbig"},"two":{"$":"hafČ"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..ac8f046
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"fakeArrayBean":{"weight":[{"$":"1kg"},{"$":"2kg"}],"color":{"$":"red"},"name":{"$":"bumper"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..ac8f046
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"fakeArrayBean":{"weight":[{"$":"1kg"},{"$":"2kg"}],"color":{"$":"red"},"name":{"$":"bumper"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray.json
new file mode 100644
index 0000000..2e64388
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":{"intArray":{"$":"4"},"integerArray":{"$":"3"},"number":{"$":"8"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..2e64388
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":{"intArray":{"$":"4"},"integerArray":{"$":"3"},"number":{"$":"8"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..c44dcdc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"jersey1199List":{"objects":[{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"colorHolder","colors":[{"$":"RED"},{"$":"BLUE"}]},{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"colorHolder","colors":{"$":"GREEN"}}],"offset":{"$":"0"},"total":{"$":"2"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..c44dcdc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"jersey1199List":{"objects":[{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"colorHolder","colors":[{"$":"RED"},{"$":"BLUE"}]},{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"colorHolder","colors":{"$":"GREEN"}}],"offset":{"$":"0"},"total":{"$":"2"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..91e8e27
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"listAndNonListBean":{"a":{"$":"1"},"d":{"$":"2"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..91e8e27
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"listAndNonListBean":{"a":{"$":"1"},"d":{"$":"2"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..0d9d148
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"listEmptyBean":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..0d9d148
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"listEmptyBean":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..bee9df5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{"item":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..bee9df5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"item":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse.json
new file mode 100644
index 0000000..9c4baca
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"myResponse":{"@xmlns":{"ns2":"http:\/\/test.jaxb.com"},"ns2:myMessage":[{"id":{"$":"0"},"text":{"$":"ok"}},{"id":{"$":"1"},"text":{"$":"ok"}}],"ns2:myError":{"id":{"$":"-1"},"desc":{"$":"error"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..575635e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"myResponse":{"@xmlns":{"ns0":"http:\/\/test.jaxb.com"},"ns0:myMessage":[{"id":{"$":"0"},"text":{"$":"ok"}},{"id":{"$":"1"},"text":{"$":"ok"}}],"ns0:myError":{"id":{"$":"-1"},"desc":{"$":"error"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..9affde6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"namespaceBean":{"@xmlns":{"ns2":"http:\/\/example.com"},"a":{"$":"foo"},"ns2:b":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..0287db4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"namespaceBeanWithAttribute":{"@xmlns":{"ns1":"http:\/\/example.com"},"@ns1:attr":"value","a":{"$":"foo"},"ns1:b":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..9223397
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"namespaceBeanWithAttribute":{"@xmlns":{"ns0":"http:\/\/example.com"},"@ns0:attr":"value","a":{"$":"foo"},"ns0:b":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..74942c4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"namespaceBean":{"@xmlns":{"ns0":"http:\/\/example.com"},"a":{"$":"foo"},"ns0:b":{"$":"bar"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean.json
new file mode 100644
index 0000000..91eb8da
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullStringBean":{"nullString":{"$":"not null to test if set to null works"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..91eb8da
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullStringBean":{"nullString":{"$":"not null to test if set to null works"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person.json
new file mode 100644
index 0000000..3196a22
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person.json
@@ -0,0 +1 @@
+{"person":{"name":{"$":"Joe Schmo"},"children":{"child":[{"name":{"$":"Jill Schmo"}},{"name":{"$":"Jack Schmo"}}]}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..3196a22
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"person":{"name":{"$":"Joe Schmo"},"children":{"child":[{"name":{"$":"Jill Schmo"}},{"name":{"$":"Jack Schmo"}}]}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..ff098bc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"pureCharDataBean":{"$":"some textual content"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..ff098bc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"pureCharDataBean":{"$":"some textual content"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..308b42b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"registerMessage":{"@requestTime":"1234","@agentUID":"agentKocka"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..d288d49
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"registerMessage":{"@agentUID":"agentKocka","@requestTime":"1234"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean.json
new file mode 100644
index 0000000..fb691d8
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"DummyOne":{"child":{"$":"simple"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..e044067
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"simpleBeanWithAttributes":{"@j":"bumper","@i":"312","@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","s1":{"$":"hi there"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..711b962
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithAttributes":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","@i":"312","@j":"bumper","s1":{"$":"hi there"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..e2ec3e2
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttribute":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..91166c6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttributeAndValue":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","$":"characters"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..91166c6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttributeAndValue":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/","$":"characters"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..e2ec3e2
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttribute":{"@uri":"http:\/\/localhost:8080\/jedna\/bedna\/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..fb691d8
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"DummyOne":{"child":{"$":"simple"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel.json
new file mode 100644
index 0000000..b9b6473
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"treeModel":{"root":{"label":{"$":"dummy node"},"expanded":{"$":"false"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..b9b6473
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"treeModel":{"root":{"label":{"$":"dummy node"},"expanded":{"$":"false"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..a06cb37
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"item2":{"property1":[{"$":"a1"},{"$":"a1"}],"property2":{"$":"b1"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..a06cb37
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"item2":{"property1":[{"$":"a1"},{"$":"a1"}],"property2":{"$":"b1"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User.json
new file mode 100644
index 0000000..a614e56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User.json
@@ -0,0 +1 @@
+{"user":{"userid":{"$":"1621"},"name":{"$":"Grotefend"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable.json
new file mode 100644
index 0000000..78f213d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"userTable":{"columns":[{"id":{"$":"userid"},"label":{"$":"UserID"}},{"id":{"$":"name"},"label":{"$":"User Name"}}],"rows":{"userid":{"$":"1621"},"name":{"$":"Grotefend"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..78f213d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"userTable":{"columns":[{"id":{"$":"userid"},"label":{"$":"UserID"}},{"id":{"$":"name"},"label":{"$":"User Name"}}],"rows":{"userid":{"$":"1621"},"name":{"$":"Grotefend"}}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User_MOXy.json
new file mode 100644
index 0000000..a614e56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonBadgerfishJsonTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"user":{"userid":{"$":"1621"},"name":{"$":"Grotefend"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList.json
new file mode 100644
index 0000000..2c42549
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animalList":{"animals":[{"@xsi.type":"dog","name":"Fifi"},{"@xsi.type":"cat","name":"Daisy"}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..2c42549
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animalList":{"animals":[{"@xsi.type":"dog","name":"Fifi"},{"@xsi.type":"cat","name":"Daisy"}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..2d1c5d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"anotherArrayTestBean":{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..2d1c5d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"anotherArrayTestBean":{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..4b41cc9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"parent":{"@attr":"aval","$":"pval"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..4b41cc9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"parent":{"@attr":"aval","$":"pval"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..4f8ff54
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes":{"@a2":"31415926","@a1":"hello dolly","filler1":111,"list":[{"@j":"bumper","@i":"312","@uri":"http://localhost:8080/jedna/bedna/","s1":"hi there"},{"@j":"bumper","@i":"312","@uri":"http://localhost:8080/jedna/bedna/","s1":"hi there"}],"filler2":222,"b":{"@j":"bumper","@i":"312","@uri":"http://localhost:8080/jedna/bedna/","s1":"hi there"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..a738f36
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes2":{"@a2":"31415926","@a1":"hello dolly","filler1":111,"list":[{"@uri":"http://localhost:8080/jedna/bedna/"},{"@uri":"http://localhost:8080/jedna/bedna/"}],"filler2":222,"b":{"@uri":"http://localhost:8080/jedna/bedna/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..457c937
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes2":{"@a1":"hello dolly","@a2":"31415926","filler1":111,"list":[{"@uri":"http://localhost:8080/jedna/bedna/"},{"@uri":"http://localhost:8080/jedna/bedna/"}],"filler2":222,"b":{"@uri":"http://localhost:8080/jedna/bedna/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..30c90d7
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes3":{"b":{"@uri":"http://localhost:8080/jedna/bedna/"},"c":{"@uri":"http://localhost:8080/jedna/bedna/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..30c90d7
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes3":{"b":{"@uri":"http://localhost:8080/jedna/bedna/"},"c":{"@uri":"http://localhost:8080/jedna/bedna/"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..66e0fe6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes4":{"b":""}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..66e0fe6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes4":{"b":""}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..5b67d07
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"complexBeanWithAttributes":{"@a1":"hello dolly","@a2":"31415926","filler1":111,"list":[{"@uri":"http://localhost:8080/jedna/bedna/","@i":"312","@j":"bumper","s1":"hi there"},{"@uri":"http://localhost:8080/jedna/bedna/","@i":"312","@j":"bumper","s1":"hi there"}],"filler2":222,"b":{"@uri":"http://localhost:8080/jedna/bedna/","@i":"312","@j":"bumper","s1":"hi there"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..f4c913e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{"emptyElementBean":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..f4c913e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyElementBean":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..1320e7f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"emptyElementContainingBean":{"c":"foo","d":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..1320e7f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"emptyElementContainingBean":{"c":"foo","d":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..e9119c3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"encodedContentBean":{"one":"\tone\n\tbig","two":"hafČ"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..e9119c3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"encodedContentBean":{"one":"\tone\n\tbig","two":"hafČ"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..657a01a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"fakeArrayBean":{"weight":["1kg","2kg"],"color":"red","name":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..657a01a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"fakeArrayBean":{"weight":["1kg","2kg"],"color":"red","name":"bumper"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray.json
new file mode 100644
index 0000000..ba9d1b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":{"intArray":4,"integerArray":3,"number":8}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..ba9d1b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":{"intArray":4,"integerArray":3,"number":8}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..2cf2ebf
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"jersey1199List":{"objects":[{"@xsi.type":"colorHolder","colors":["RED","BLUE"]},{"@xsi.type":"colorHolder","colors":"GREEN"}],"offset":0,"total":2}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..2cf2ebf
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"jersey1199List":{"objects":[{"@xsi.type":"colorHolder","colors":["RED","BLUE"]},{"@xsi.type":"colorHolder","colors":"GREEN"}],"offset":0,"total":2}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..d8db897
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"listAndNonListBean":{"a":1,"d":2}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..d8db897
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"listAndNonListBean":{"a":1,"d":2}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..5206895
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"listEmptyBean":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..5206895
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"listEmptyBean":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..ca068e9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{"item":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..ca068e9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"item":""}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse.json
new file mode 100644
index 0000000..6b29b6e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"myResponse":{"jaxb.myMessage":[{"id":0,"text":"ok"},{"id":1,"text":"ok"}],"jaxb.myError":{"id":-1,"desc":"error"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..6b29b6e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"myResponse":{"jaxb.myMessage":[{"id":0,"text":"ok"},{"id":1,"text":"ok"}],"jaxb.myError":{"id":-1,"desc":"error"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..4f95fa4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"namespaceBean":{"a":"foo","example.b":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..64e418a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"namespaceBeanWithAttribute":{"@example.attr":"value","a":"foo","example.b":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..64e418a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"namespaceBeanWithAttribute":{"@example.attr":"value","a":"foo","example.b":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..4f95fa4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"namespaceBean":{"a":"foo","example.b":"bar"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean.json
new file mode 100644
index 0000000..f3b4a4d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullStringBean":{"nullString":"not null to test if set to null works"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..f3b4a4d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullStringBean":{"nullString":"not null to test if set to null works"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person.json
new file mode 100644
index 0000000..29a732e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person.json
@@ -0,0 +1 @@
+{"person":{"name":"Joe Schmo","children":{"child":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..29a732e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"person":{"name":"Joe Schmo","children":{"child":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..43044be
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"pureCharDataBean":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..43044be
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"pureCharDataBean":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..308b42b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"registerMessage":{"@requestTime":"1234","@agentUID":"agentKocka"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..d288d49
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"registerMessage":{"@agentUID":"agentKocka","@requestTime":"1234"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean.json
new file mode 100644
index 0000000..20eb30b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"DummyOne":{"child":"simple"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..09bb1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"simpleBeanWithAttributes":{"@j":"bumper","@i":"312","@uri":"http://localhost:8080/jedna/bedna/","s1":"hi there"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..6be03ab
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithAttributes":{"@uri":"http://localhost:8080/jedna/bedna/","@i":"312","@j":"bumper","s1":"hi there"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..ba42175
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttribute":{"@uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..8b18cf7
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttributeAndValue":{"@uri":"http://localhost:8080/jedna/bedna/","$":"characters"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..8b18cf7
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttributeAndValue":{"@uri":"http://localhost:8080/jedna/bedna/","$":"characters"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..ba42175
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"simpleBeanWithJustOneAttribute":{"@uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..20eb30b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"DummyOne":{"child":"simple"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean.json
new file mode 100644
index 0000000..1435abb
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean.json
@@ -0,0 +1 @@
+{"singleItemListWrapper":{"singleItemList":[1]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean_MOXy.json
new file mode 100644
index 0000000..1435abb
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_SingleItemListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"singleItemListWrapper":{"singleItemList":[1]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel.json
new file mode 100644
index 0000000..1b601d4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"treeModel":{"root":{"label":"dummy node","expanded":false}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..1b601d4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"treeModel":{"root":{"label":"dummy node","expanded":false}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..9a23326
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"item2":{"property1":["a1","a1"],"property2":"b1"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..9a23326
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"item2":{"property1":["a1","a1"],"property2":"b1"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User.json
new file mode 100644
index 0000000..a57ef80
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User.json
@@ -0,0 +1 @@
+{"user":{"userid":1621,"name":"Grotefend"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable.json
new file mode 100644
index 0000000..eed2f18
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"userTable":{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":{"userid":1621,"name":"Grotefend"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..eed2f18
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"userTable":{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":{"userid":1621,"name":"Grotefend"}}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User_MOXy.json
new file mode 100644
index 0000000..a57ef80
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JettisonMappedJsonTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"user":{"userid":1621,"name":"Grotefend"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList.json
new file mode 100644
index 0000000..3da277e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"Dog","name":"Fifi"},{"@type":"Cat","nickName":null,"name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..976ae9b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"className":"org.glassfish.jersey.tests.e2e.json.entity.Dog","instance":{"name":"Fifi"}},{"className":"org.glassfish.jersey.tests.e2e.json.entity.Cat","instance":{"name":"Daisy"}}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..d9dc02f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..d9dc02f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..0e88b3c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"b":{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"},"filler1":"111","filler2":"222","list":[{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"},{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..80d87b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"b":{"uri":"http://localhost:8080/jedna/bedna/"},"filler1":"111","filler2":"222","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..80d87b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"b":{"uri":"http://localhost:8080/jedna/bedna/"},"filler1":"111","filler2":"222","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..cc0012f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"b":{},"list":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..cc0012f
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"b":{},"list":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..0e88b3c
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"b":{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"},"filler1":"111","filler2":"222","list":[{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"},{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"}]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..34819f9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..34819f9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..6c93316
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"color":"red","name":"bumper","weight":["1kg","2kg"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..23c8825
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"color":"red","name":"bumper","weight":["1kg","2kg"]}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..488cba2
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"objects":[{"colors":["RED","BLUE"]},{"colors":["GREEN"]}],"offset":0,"total":2}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..488cba2
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"objects":[{"colors":["RED","BLUE"]},{"colors":["GREEN"]}],"offset":0,"total":2}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..379160e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property":null}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse.json
new file mode 100644
index 0000000..303d04e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"myError":{"desc":"error","id":"-1"},"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..303d04e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"myError":{"desc":"error","id":"-1"},"myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..ce17ce5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"a":"foo","attr":"value","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..9915729
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"a":"foo","attr":"value","b":"bar"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..0386d5d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"a":"foo","b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person.json
new file mode 100644
index 0000000..84f9dcd
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person.json
@@ -0,0 +1 @@
+{"children":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}],"name":"Joe Schmo"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..7a660ed
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"children":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}],"name":"Joe Schmo"}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList.json
new file mode 100644
index 0000000..2a49520
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","nickName":null,"name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList_MOXy.json
new file mode 100644
index 0000000..2a49520
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PojoAnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"@type":"PojoDog","name":"Fifi"},{"@type":"PojoCat","nickName":null,"name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..9bdbc2b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"content":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..9bdbc2b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"content":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..498818a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..498818a
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"i":312,"j":"bumper","s1":"hi there","uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel.json
new file mode 100644
index 0000000..f6d35c1
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"root":{"expanded":false,"label":"dummy node"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..6b6746b
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"root":{"expanded":false,"label":"dummy node"}}
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User.json
new file mode 100644
index 0000000..7560ef0
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User.json
@@ -0,0 +1 @@
+{"id":"1621","name":"Grotefend"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable.json
new file mode 100644
index 0000000..8f15bbd
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"id":"1621","name":"Grotefend"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..8f15bbd
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"id":"1621","name":"Grotefend"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User_MOXy.json
new file mode 100644
index 0000000..7560ef0
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/JsonbTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"id":"1621","name":"Grotefend"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList.json
new file mode 100644
index 0000000..51e361e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList.json
@@ -0,0 +1 @@
+{"animals":[{"xsi:type":"dog","name":"Fifi"},{"xsi:type":"cat","name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList_MOXy.json
new file mode 100644
index 0000000..51e361e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnimalList_MOXy.json
@@ -0,0 +1 @@
+{"animals":[{"xsi:type":"dog","name":"Fifi"},{"xsi:type":"cat","name":"Daisy"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean.json
new file mode 100644
index 0000000..dfb3702
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean_MOXy.json
new file mode 100644
index 0000000..dfb3702
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AnotherArrayTestBean_MOXy.json
@@ -0,0 +1 @@
+{"cats":[{"name":"Foo","nickName":"Kitty"},{"name":"Bar","nickName":"Puss"}],"prop":"testProp"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean_MOXy.json
new file mode 100644
index 0000000..765e1f5
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_AttrAndCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"attr":"aval","value":"pval"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes.json
new file mode 100644
index 0000000..ae04acc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"},{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
new file mode 100644
index 0000000..0a3dd56
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes2_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/"},{"uri":"http://localhost:8080/jedna/bedna/"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
new file mode 100644
index 0000000..7dd6379
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes3_MOXy.json
@@ -0,0 +1 @@
+{"b":{"uri":"http://localhost:8080/jedna/bedna/"},"c":{"uri":"http://localhost:8080/jedna/bedna/"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4.json
new file mode 100644
index 0000000..c724b09
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4.json
@@ -0,0 +1 @@
+{"list":[],"b":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
new file mode 100644
index 0000000..c724b09
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes4_MOXy.json
@@ -0,0 +1 @@
+{"list":[],"b":{}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..ae04acc
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ComplexBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"a1":"hello dolly","a2":31415926,"filler1":"111","list":[{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"},{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}],"filler2":"222","b":{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean_MOXy.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementBean_MOXy.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean.json
new file mode 100644
index 0000000..34819f9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean.json
@@ -0,0 +1 @@
+{"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean_MOXy.json
new file mode 100644
index 0000000..34819f9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EmptyElementContainingBean_MOXy.json
@@ -0,0 +1 @@
+{"c":"foo","d":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean_MOXy.json
new file mode 100644
index 0000000..b4de3a6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_EncodedContentBean_MOXy.json
@@ -0,0 +1 @@
+{"one":"\tone\n\tbig","two":"hafČ"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean_MOXy.json
new file mode 100644
index 0000000..f32b098
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_FakeArrayBean_MOXy.json
@@ -0,0 +1 @@
+{"weight":["1kg","2kg"],"color":"red","name":"bumper"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray_MOXy.json
new file mode 100644
index 0000000..4445714
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_IntArray_MOXy.json
@@ -0,0 +1 @@
+{"intArray":[4],"integerArray":[3],"number":8}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List.json
new file mode 100644
index 0000000..7481af3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List.json
@@ -0,0 +1 @@
+{"objects":[{"xsi:type":"colorHolder","colors":["RED","BLUE"]},{"xsi:type":"colorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List_MOXy.json
new file mode 100644
index 0000000..7481af3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Jersey1199List_MOXy.json
@@ -0,0 +1 @@
+{"objects":[{"xsi:type":"colorHolder","colors":["RED","BLUE"]},{"xsi:type":"colorHolder","colors":["GREEN"]}],"offset":0,"total":2}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean_MOXy.json
new file mode 100644
index 0000000..f85cad9
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListAndNonListBean_MOXy.json
@@ -0,0 +1 @@
+{"a":["1"],"d":"2"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean_MOXy.json
new file mode 100644
index 0000000..b5a9f53
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListEmptyBean_MOXy.json
@@ -0,0 +1 @@
+{"empty":[]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean_MOXy.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_ListWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse.json
new file mode 100644
index 0000000..b054d67
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse.json
@@ -0,0 +1 @@
+{"jaxb:myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"jaxb:myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse_MOXy.json
new file mode 100644
index 0000000..b054d67
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_MyResponse_MOXy.json
@@ -0,0 +1 @@
+{"jaxb:myMessage":[{"id":"0","text":"ok"},{"id":"1","text":"ok"}],"jaxb:myError":{"id":"-1","desc":"error"}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean.json
new file mode 100644
index 0000000..c8df655
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean.json
@@ -0,0 +1 @@
+{"a":"foo","example:b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute.json
new file mode 100644
index 0000000..6158c88
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute.json
@@ -0,0 +1 @@
+{"example:attr":"value","a":"foo","example:b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
new file mode 100644
index 0000000..6158c88
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBeanWithAttribute_MOXy.json
@@ -0,0 +1 @@
+{"example:attr":"value","a":"foo","example:b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean_MOXy.json
new file mode 100644
index 0000000..c8df655
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NamespaceBean_MOXy.json
@@ -0,0 +1 @@
+{"a":"foo","example:b":"bar"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean_MOXy.json
new file mode 100644
index 0000000..4a8cd3d
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_NullStringBean_MOXy.json
@@ -0,0 +1 @@
+{"nullString":"not null to test if set to null works"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person.json
new file mode 100644
index 0000000..8ccd39e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","children":{"child":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person_MOXy.json
new file mode 100644
index 0000000..8ccd39e
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_Person_MOXy.json
@@ -0,0 +1 @@
+{"name":"Joe Schmo","children":{"child":[{"name":"Jill Schmo"},{"name":"Jack Schmo"}]}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean_MOXy.json
new file mode 100644
index 0000000..13d3153
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_PureCharDataBean_MOXy.json
@@ -0,0 +1 @@
+{"value":"some textual content"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage_MOXy.json
new file mode 100644
index 0000000..49f49b3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_RegisterMessage_MOXy.json
@@ -0,0 +1 @@
+{"agentUID":"agentKocka","requestTime":1234}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes.json
new file mode 100644
index 0000000..bed08d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
new file mode 100644
index 0000000..bed08d6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithAttributes_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","i":312,"j":"bumper","s1":"hi there"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
new file mode 100644
index 0000000..8beca20
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttributeAndValue_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/","value":"characters"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
new file mode 100644
index 0000000..a989896
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBeanWithJustOneAttribute_MOXy.json
@@ -0,0 +1 @@
+{"uri":"http://localhost:8080/jedna/bedna/"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean_MOXy.json
new file mode 100644
index 0000000..0f380b4
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_SimpleBean_MOXy.json
@@ -0,0 +1 @@
+{"child":"simple"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel.json
new file mode 100644
index 0000000..7ffadb3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel_MOXy.json
new file mode 100644
index 0000000..7ffadb3
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TreeModel_MOXy.json
@@ -0,0 +1 @@
+{"root":{"label":"dummy node","expanded":false}}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean_MOXy.json
new file mode 100644
index 0000000..d4ff239
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_TwoListsWrapperBean_MOXy.json
@@ -0,0 +1 @@
+{"property1":["a1","a1"],"property2":["b1"]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User.json
new file mode 100644
index 0000000..a1b91b6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User.json
@@ -0,0 +1 @@
+{"userid":"1621","name":"Grotefend"}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable.json
new file mode 100644
index 0000000..2652195
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"userid":"1621","name":"Grotefend"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable_MOXy.json
new file mode 100644
index 0000000..2652195
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_UserTable_MOXy.json
@@ -0,0 +1 @@
+{"columns":[{"id":"userid","label":"UserID"},{"id":"name","label":"User Name"}],"rows":[{"userid":"1621","name":"Grotefend"}]}
\ No newline at end of file
diff --git a/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User_MOXy.json b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User_MOXy.json
new file mode 100644
index 0000000..a1b91b6
--- /dev/null
+++ b/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/json/entity/MoxyJsonTestProvider_User_MOXy.json
@@ -0,0 +1 @@
+{"userid":"1621","name":"Grotefend"}
\ No newline at end of file
diff --git a/tests/e2e-inject/cdi2-se/pom.xml b/tests/e2e-inject/cdi2-se/pom.xml
new file mode 100644
index 0000000..86c9156
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>e2e-inject</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-inject-cdi2-se</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-inject-cdi-se</name>
+
+ <description>Jersey E2E Inject CDI SE tests</description>
+
+ <properties>
+ <cdi.api.version>2.0</cdi.api.version>
+ <weld.version>${weld3.version}</weld.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.inject</groupId>
+ <artifactId>jersey-cdi2-se</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Account.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Account.java
new file mode 100644
index 0000000..7651449
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Account.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+
+/**
+ * Keeps current state of money.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class Account {
+
+ private long current = 0;
+
+ public void observeCredit(@Observes @Credit Long amount) {
+ current += amount;
+ }
+
+ public void observeDebit(@Observes @Debit Long amount) {
+ current -= amount;
+ }
+
+ public long getCurrent() {
+ return current;
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/AccountResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/AccountResource.java
new file mode 100644
index 0000000..5073fad
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/AccountResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+/**
+ * Testing resource for CDI events.
+ *
+ * @author Petr Bouda
+ */
+@Path("account")
+public class AccountResource {
+
+ @Inject
+ @Credit
+ private Event<Long> creditEvent;
+
+ @Inject
+ @Debit
+ private Event<Long> debitEvent;
+
+ @Inject
+ private Account account;
+
+ @POST
+ public void credit(@QueryParam("amount") long amount) {
+ creditEvent.fire(amount);
+ }
+
+ @DELETE
+ public void debit(@QueryParam("amount") long amount) {
+ debitEvent.fire(amount);
+ }
+
+ @GET
+ public long current() {
+ return account.getCurrent();
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Credit.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Credit.java
new file mode 100644
index 0000000..be693da
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Credit.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Event qualifier.
+ *
+ * @author Petr Bouda
+ */
+@Qualifier
+@Target({METHOD, FIELD, PARAMETER, TYPE})
+@Retention(RUNTIME)
+public @interface Credit {
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Debit.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Debit.java
new file mode 100644
index 0000000..adef1fc
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Debit.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Event qualifier.
+ *
+ * @author Petr Bouda
+ */
+@Qualifier
+@Target({METHOD, FIELD, PARAMETER, TYPE})
+@Retention(RUNTIME)
+public @interface Debit {
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Hello.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Hello.java
new file mode 100644
index 0000000..da76a10
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Hello.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+/**
+ * Interface used to activate decorator.
+ *
+ * @author Petr Bouda
+ */
+public interface Hello {
+
+ String hello();
+
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloResource.java
new file mode 100644
index 0000000..9780494
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloResource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.inject.Inject;
+
+/**
+ * Intercepted and decorated resource.
+ *
+ * @author Petr Bouda
+ */
+@Secured
+@Path("intercepted")
+public class HelloResource implements Hello {
+
+ @Inject
+ private NameService service;
+
+ @GET
+ @Override
+ public String hello() {
+ return "Hello " + service.getName();
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloStarDecorator.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloStarDecorator.java
new file mode 100644
index 0000000..cba9ebf
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/HelloStarDecorator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.decorator.Decorator;
+import javax.decorator.Delegate;
+import javax.enterprise.inject.Any;
+import javax.inject.Inject;
+
+/**
+ * Decorator wraps the hello resource by stars.
+ *
+ * @author Petr Bouda
+ */
+@Decorator
+public class HelloStarDecorator implements Hello {
+
+ @Inject
+ @Delegate
+ @Any
+ Hello account;
+
+ @Override
+ public String hello() {
+ return "***" + account.hello() + "***";
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/JaxrsService.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/JaxrsService.java
new file mode 100644
index 0000000..5a708be
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/JaxrsService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Holder for JAX-RS information to inject them into interceptor. JAX-RS does not work in interceptor.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class JaxrsService {
+
+ @Context
+ private UriInfo uriInfo;
+
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/NameService.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/NameService.java
new file mode 100644
index 0000000..6aa4555
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/NameService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Service returning the name.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class NameService {
+
+ public static final String NAME = "James";
+
+ public String getName() {
+ return NAME;
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Secured.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Secured.java
new file mode 100644
index 0000000..762ca0e
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/Secured.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.interceptor.InterceptorBinding;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Security annotation bound to {@link SecurityInterceptor}.
+ *
+ * @author Petr Bouda
+ */
+@Inherited
+@InterceptorBinding
+@Retention(RUNTIME)
+@Target({ METHOD, TYPE })
+public @interface Secured {
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/SecurityInterceptor.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/SecurityInterceptor.java
new file mode 100644
index 0000000..5beae95
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/SecurityInterceptor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.core.MultivaluedMap;
+
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+/**
+ * Interceptor checking James as a user in query params.
+ *
+ * @author Petr Bouda
+ */
+@Secured
+@Interceptor
+public class SecurityInterceptor {
+
+ @Inject
+ NameService nameService;
+
+ @Inject
+ JaxrsService jaxrsService;
+
+ @AroundInvoke
+ public Object logMethodEntry(InvocationContext ctx) throws Exception {
+ MultivaluedMap<String, String> params = jaxrsService.getUriInfo().getQueryParameters();
+ String user = params.getFirst("user");
+
+ if (nameService.getName().equals(user)) {
+ return ctx.proceed();
+ } else {
+ throw new ForbiddenException("Forbidden resource for the user: " + user);
+ }
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ApplicationCounterBean.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ApplicationCounterBean.java
new file mode 100644
index 0000000..2830975
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ApplicationCounterBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.scopes;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Request counter.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class ApplicationCounterBean {
+
+ private AtomicInteger counter = new AtomicInteger();
+
+ public int getNumber() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/RequestScopedResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/RequestScopedResource.java
new file mode 100644
index 0000000..2d77691
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/RequestScopedResource.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.scopes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.process.internal.RequestScoped;
+
+/**
+ * Request scoped resource.
+ *
+ * @author Petr Bouda
+ */
+@RequestScoped
+@Path("request")
+public class RequestScopedResource {
+
+ @Inject
+ private ApplicationCounterBean application;
+
+ @PathParam("name")
+ private String name;
+
+ private UriInfo uriInfo;
+
+ public RequestScopedResource(@Context UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ }
+
+ @GET
+ @Path("{name}")
+ @Produces("text/plain")
+ public String getHello() {
+ return "Hello_" + name + " [" + application.getNumber() + "] " + "[" + uriInfo.getPath() + "] " + this;
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/SingletonScopedResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/SingletonScopedResource.java
new file mode 100644
index 0000000..6551a1e
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/SingletonScopedResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.scopes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Singleton Resource.
+ *
+ * @author Petr Bouda
+ */
+@Singleton
+@Path("singleton")
+public class SingletonScopedResource {
+
+ @Inject
+ private ApplicationCounterBean application;
+
+ @Context
+ private UriInfo uriInfo;
+
+ @GET
+ @Path("{name}")
+ @Produces("text/plain")
+ public String getHello(@PathParam("name") String name) {
+ return "Hello_" + name + " [" + application.getNumber() + "] " + "[" + uriInfo.getPath() + "] " + this;
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorFeature.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorFeature.java
new file mode 100644
index 0000000..b4780ad
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorFeature.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.subresources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+import javax.annotation.Priority;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.model.ModelProcessor;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceModel;
+
+public class ModelProcessorFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(SimpleModelProcessor.class);
+ return true;
+ }
+
+ @Priority(5000)
+ public static class SimpleModelProcessor implements ModelProcessor {
+
+ @Override
+ public ResourceModel processResourceModel(ResourceModel resourceModel, Configuration configuration) {
+ ResourceModel.Builder builder = new ResourceModel.Builder(resourceModel.getRootResources(), false);
+ final Resource singletonResource = Resource.from(SingletonResource.class);
+ builder.addResource(singletonResource);
+
+ final Resource requestScopeResource = Resource.from(RequestScopeResource.class);
+ builder.addResource(requestScopeResource);
+
+ final Resource.Builder resourceBuilder = Resource.builder("instance");
+ resourceBuilder.addMethod("GET").handledBy(new Inflector<ContainerRequestContext, String>() {
+ private int counter = 0;
+
+ @Override
+ public String apply(ContainerRequestContext containerRequestContext) {
+ return String.valueOf("Inflector:" + counter++);
+ }
+ });
+ final Resource instanceResource = resourceBuilder.build();
+
+ builder.addResource(instanceResource);
+
+ return builder.build();
+ }
+
+ @Override
+ public ResourceModel processSubResource(ResourceModel subResource, Configuration configuration) {
+ final Resource resource = Resource.builder()
+ .mergeWith(Resource.from(EnhancedSubResourceSingleton.class))
+ .mergeWith(Resource.from(EnhancedSubResource.class))
+ .mergeWith(subResource.getResources().get(0)).build();
+
+ return new ResourceModel.Builder(true).addResource(resource).build();
+ }
+ }
+
+ @Singleton
+ public static class EnhancedSubResourceSingleton {
+ private int counter = 0;
+
+ @GET
+ @Path("enhanced-singleton")
+ public String get() {
+ return "EnhancedSubResourceSingleton:" + String.valueOf(counter++);
+ }
+ }
+
+ public static class EnhancedSubResource {
+
+ private int counter = 0;
+
+ @GET
+ @Path("enhanced")
+ public String get() {
+ return String.valueOf("EnhancedSubResource:" + counter++);
+ }
+ }
+
+ @Path("request-scope")
+ public static class RequestScopeResource {
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("RequestScopeResource:" + counter++);
+ }
+ }
+
+ @Path("singleton")
+ @Singleton
+ public static class SingletonResource {
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("SingletonResource:" + counter++);
+ }
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootResource.java
new file mode 100644
index 0000000..3ea11db
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.subresources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("root")
+public class RootResource {
+
+ @GET
+ public String get() {
+ return "root";
+ }
+
+ @Path("sub-resource-singleton")
+ public Class<SubResourceSingleton> getSubResourceSingleton() {
+ return SubResourceSingleton.class;
+ }
+
+ @Path("sub-resource-instance")
+ public SubResourceSingleton getSubResourceSingletonInstance() {
+ return new SubResourceSingleton();
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootSingletonResource.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootSingletonResource.java
new file mode 100644
index 0000000..fa178d7
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/RootSingletonResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.subresources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.inject.Singleton;
+
+@Path("root-singleton")
+@Singleton
+public class RootSingletonResource {
+
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return "RootSingletonResource:" + String.valueOf(counter++);
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/SubResourceSingleton.java b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/SubResourceSingleton.java
new file mode 100644
index 0000000..c1dbd3b
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/SubResourceSingleton.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.subresources;
+
+import javax.ws.rs.GET;
+
+import javax.inject.Singleton;
+
+@Singleton
+public class SubResourceSingleton {
+
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("SubResourceSingleton:" + counter++);
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml b/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..ae84224
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans>
+ <interceptors>
+ <class>org.glassfish.jersey.tests.e2e.inject.cdi.se.SecurityInterceptor</class>
+ </interceptors>
+ <decorators>
+ <class>org.glassfish.jersey.tests.e2e.inject.cdi.se.HelloStarDecorator</class>
+ </decorators>
+</beans>
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/EventsTest.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/EventsTest.java
new file mode 100644
index 0000000..e642750
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/EventsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the resource can fire an event.
+ *
+ * @author Petr Bouda
+ */
+public class EventsTest extends JerseyTest{
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(AccountResource.class);
+ }
+
+ @Test
+ public void testFiredEvents() {
+ Response credit = target("account").queryParam("amount", 50).request().post(Entity.json(""));
+ assertEquals(204, credit.getStatus());
+
+ Response debit = target("account").queryParam("amount", 25).request().delete();
+ assertEquals(204, debit.getStatus());
+
+ Long current = target("account").queryParam("amount", 25).request().get(Long.class);
+ assertEquals(25, current.longValue());
+ }
+
+}
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/InterceptorDecoratorTest.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/InterceptorDecoratorTest.java
new file mode 100644
index 0000000..b3f70a3
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/InterceptorDecoratorTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the resource can be intercepted and decorated.
+ *
+ * @author Petr Bouda
+ */
+public class InterceptorDecoratorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HelloResource.class);
+ }
+
+ @Test
+ public void testInterceptedGet() {
+ String intercepted = target("intercepted").queryParam("user", NameService.NAME).request().get(String.class);
+ assertEquals("***Hello James***", intercepted);
+ }
+
+ @Test
+ public void testForbiddenGet() {
+ Response result = target("intercepted").queryParam("user", "unknown").request().get();
+ assertEquals(403, result.getStatus());
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java
new file mode 100644
index 0000000..3b06a47
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.RuntimeDelegate;
+import javax.ws.rs.ext.WriterInterceptor;
+
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.HeaderUtils;
+import org.glassfish.jersey.server.ContainerRequest;
+
+/**
+ * Used by tests to create mock JerseyContainerRequestContext instances.
+ *
+ * @author Martin Matula
+ */
+public class RequestContextBuilder {
+
+ public class TestContainerRequest extends ContainerRequest {
+
+ private Object entity;
+ private GenericType entityType;
+ private final PropertiesDelegate propertiesDelegate;
+
+ public TestContainerRequest(final URI baseUri,
+ final URI requestUri,
+ final String method,
+ final SecurityContext securityContext,
+ final PropertiesDelegate propertiesDelegate) {
+ super(baseUri, requestUri, method, securityContext, propertiesDelegate);
+ this.propertiesDelegate = propertiesDelegate;
+ }
+
+ public void setEntity(final Object entity) {
+ if (entity instanceof GenericEntity) {
+ this.entity = ((GenericEntity) entity).getEntity();
+ this.entityType = new GenericType(((GenericEntity) entity).getType());
+ } else {
+ this.entity = entity;
+ this.entityType = new GenericType(entity.getClass());
+ }
+ }
+
+ @Override
+ public void setWorkers(final MessageBodyWorkers workers) {
+ super.setWorkers(workers);
+ final byte[] entityBytes;
+ if (entity != null) {
+ final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStream stream = null;
+ try {
+ stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
+ new Annotation[0], getMediaType(),
+ myMap,
+ propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
+ } catch (final IOException | WebApplicationException ex) {
+ Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (final IOException e) {
+ // ignore
+ }
+ }
+ }
+ entityBytes = baos.toByteArray();
+ } else {
+ entityBytes = new byte[0];
+ }
+ setEntityStream(new ByteArrayInputStream(entityBytes));
+ }
+ }
+
+ private final RuntimeDelegate delegate = RuntimeDelegate.getInstance();
+ private final TestContainerRequest request;
+
+ public static RequestContextBuilder from(final String requestUri, final String method) {
+ return from(null, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final String baseUri, final String requestUri, final String method) {
+ return new RequestContextBuilder(baseUri, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final URI requestUri, final String method) {
+ return from(null, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final URI baseUri, final URI requestUri, final String method) {
+ return new RequestContextBuilder(baseUri, requestUri, method);
+ }
+
+ private RequestContextBuilder(final String baseUri, final String requestUri, final String method) {
+ this(baseUri == null || baseUri.isEmpty() ? null : URI.create(baseUri), URI.create(requestUri), method);
+ }
+
+ private RequestContextBuilder(final URI baseUri, final URI requestUri, final String method) {
+ request = new TestContainerRequest(baseUri, requestUri, method, null,
+ new MapPropertiesDelegate());
+ }
+
+ public ContainerRequest build() {
+ return request;
+ }
+
+ public RequestContextBuilder accept(final String... acceptHeader) {
+ putHeaders(HttpHeaders.ACCEPT, acceptHeader);
+ return this;
+ }
+
+ public RequestContextBuilder accept(final MediaType... acceptHeader) {
+ putHeaders(HttpHeaders.ACCEPT, (Object[]) acceptHeader);
+ return this;
+ }
+
+ public RequestContextBuilder entity(final Object entity) {
+ request.setEntity(entity);
+ return this;
+ }
+
+ public RequestContextBuilder type(final String contentType) {
+ request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, contentType);
+ return this;
+
+ }
+
+ public RequestContextBuilder type(final MediaType contentType) {
+ request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, HeaderUtils.asString(contentType, delegate));
+ return this;
+ }
+
+ public RequestContextBuilder header(final String name, final Object value) {
+ putHeader(name, value);
+ return this;
+ }
+
+ public RequestContextBuilder cookie(final Cookie cookie) {
+ putHeader(HttpHeaders.COOKIE, cookie);
+ return this;
+ }
+
+ public RequestContextBuilder cookies(final Cookie... cookies) {
+ putHeaders(HttpHeaders.COOKIE, (Object[]) cookies);
+ return this;
+ }
+
+ private void putHeader(final String name, final Object value) {
+ if (value == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.header(name, HeaderUtils.asString(value, delegate));
+ }
+
+ private void putHeaders(final String name, final Object... values) {
+ if (values == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.getHeaders().addAll(name, HeaderUtils.asStringList(Arrays.asList(values), delegate));
+ }
+
+ private void putHeaders(final String name, final String... values) {
+ if (values == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.getHeaders().addAll(name, values);
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ScopesTest.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ScopesTest.java
new file mode 100644
index 0000000..96be176
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/scopes/ScopesTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.scopes;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * Tests CDI resources.
+ */
+public class ScopesTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(RequestScopedResource.class, SingletonScopedResource.class);
+ }
+
+ @Test
+ public void testCheckRequest() throws InterruptedException {
+ String[] response1 = target().path("request").path("James").request().get(String.class).split(" ");
+ String[] response2 = target().path("request").path("Marcus").request().get(String.class).split(" ");
+ assertResponses("request", response1, response2);
+ assertNotEquals(response1[3], response2[3]);
+ }
+
+ @Test
+ public void testCheckSingleton() throws InterruptedException {
+ String[] response1 = target().path("singleton").path("James").request().get(String.class).split(" ");
+ String[] response2 = target().path("singleton").path("Marcus").request().get(String.class).split(" ");
+ assertResponses("singleton", response1, response2);
+ assertEquals(response1[3], response2[3]);
+ }
+
+ private void assertResponses(String type, String[] response1, String[] response2) {
+ assertEquals("Hello_James", response1[0]);
+ assertEquals("[1]", response1[1]);
+ assertEquals("[" + type + "/James]", response1[2]);
+
+ assertEquals("Hello_Marcus", response2[0]);
+ assertEquals("[2]", response2[1]);
+ assertEquals("[" + type + "/Marcus]", response2[2]);
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorScopeTest.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorScopeTest.java
new file mode 100644
index 0000000..c431a65
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/subresources/ModelProcessorScopeTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.se.subresources;
+
+import java.util.concurrent.ExecutionException;
+
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.e2e.inject.cdi.se.RequestContextBuilder;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test scope of resources enhanced by model processors.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class ModelProcessorScopeTest {
+
+ private void _testCounter(ApplicationHandler applicationHandler, String requestUri, final String prefix,
+ final String expectedSecondHit) throws
+ InterruptedException, ExecutionException {
+ ContainerResponse response = applicationHandler.apply(RequestContextBuilder.from(requestUri,
+ "GET").build()).get();
+ assertEquals(200, response.getStatus());
+ assertEquals(prefix + ":0", response.getEntity());
+ response = applicationHandler.apply(RequestContextBuilder.from(requestUri,
+ "GET").build()).get();
+ assertEquals(prefix + ":" + expectedSecondHit, response.getEntity());
+ }
+
+ @Test
+ public void testSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ModelProcessorFeature
+ .SingletonResource.class));
+ final String requestUri = "/singleton";
+ _testCounter(applicationHandler, requestUri, "SingletonResource", "1");
+ }
+
+ @Test
+ public void testSingletonInModelProcessor() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ ModelProcessorFeature.class));
+ final String requestUri = "/singleton";
+ _testCounter(applicationHandler, requestUri, "SingletonResource", "1");
+ }
+
+ @Test
+ public void testSubResourceSingletonInOriginalModel() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton";
+ _testCounter(applicationHandler, requestUri, "SubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceEnhancedSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton/enhanced-singleton";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceInstanceEnhancedSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-instance/enhanced-singleton";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceInstanceEnhancedSubResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-instance/enhanced";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResource", "0");
+ }
+
+ @Test
+ public void testSubResourceEnhancedSubResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton/enhanced";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResource", "0");
+ }
+
+ @Test
+ public void testInstanceInModelProcessor() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ ModelProcessorFeature.class));
+ final String requestUri = "/instance";
+ _testCounter(applicationHandler, requestUri, "Inflector", "1");
+ }
+
+ @Test
+ public void testRootSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ RootSingletonResource.class));
+ final String requestUri = "/root-singleton";
+ _testCounter(applicationHandler, requestUri, "RootSingletonResource", "1");
+ }
+
+ @Test
+ public void testRequestScopeResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ RootSingletonResource.class, ModelProcessorFeature.class));
+ final String requestUri = "/request-scope";
+ _testCounter(applicationHandler, requestUri, "RequestScopeResource", "0");
+ }
+}
diff --git a/tests/e2e-inject/cdi2-se/src/test/resources/surefire.policy b/tests/e2e-inject/cdi2-se/src/test/resources/surefire.policy
new file mode 100644
index 0000000..4e99a5d
--- /dev/null
+++ b/tests/e2e-inject/cdi2-se/src/test/resources/surefire.policy
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// we do not care about java lib itself
+grant codebase "file:${java.home}/-" {
+ permission java.security.AllPermission;
+};
+
+// we do not care about our dependencies
+grant codebase "file:${settings.localRepository}/-" {
+ permission java.security.AllPermission;
+};
+
+// this is to be able to set runtime delegate instance in jax-rs from the tests
+// and to run multi-threaded tests
+grant codebase "file:${project.build.directory}/test-classes/-" {
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "write";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
+
+grant codebase "file:${project.build.directory}/classes/-" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
diff --git a/tests/e2e-inject/pom.xml b/tests/e2e-inject/pom.xml
new file mode 100644
index 0000000..97ed3f8
--- /dev/null
+++ b/tests/e2e-inject/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-inject</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-e2e-inject</name>
+
+ <description>Jersey E2E Inject tests</description>
+
+ <modules>
+ <module>cdi2-se</module>
+ </modules>
+</project>
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
new file mode 100644
index 0000000..6e7ecd9
--- /dev/null
+++ b/tests/e2e-server/pom.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-server</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-server</name>
+
+ <description>Jersey E2E Server tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-freemarker</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-mustache</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson1</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jettison</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth2-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AbstractDisableMetainfServicesLookupTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AbstractDisableMetainfServicesLookupTest.java
new file mode 100644
index 0000000..3520675
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AbstractDisableMetainfServicesLookupTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.ServiceFinderBinder;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+
+/**
+ * This is base for tests testing enabling/disabling configuration property
+ * {@link org.glassfish.jersey.server.ServerProperties#METAINF_SERVICES_LOOKUP_DISABLE}.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public abstract class AbstractDisableMetainfServicesLookupTest extends JerseyTest {
+
+ protected void testGet(int expectedGetResponseCode, int expectedPostResponseCode) throws Exception {
+ final String name = "Jersey";
+ {
+ Response response = target("/").path(name).request().get();
+ Assert.assertEquals(expectedGetResponseCode, response.getStatus());
+
+ if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
+ UselessMessage entity = response.readEntity(UselessMessage.class);
+ if (entity != null) {
+ Assert.assertEquals("Hello " + name, entity.getMessage());
+ }
+ }
+ }
+ {
+ Entity<UselessMessage> uselessMessageEntity = Entity.entity(new UselessMessage(name), MediaType.TEXT_PLAIN_TYPE);
+ Response response = target("/").request().post(uselessMessageEntity);
+ Assert.assertEquals(expectedPostResponseCode, response.getStatus());
+
+ if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
+ String entity = response.readEntity(String.class);
+ if (entity.length() > 0) {
+ Assert.assertEquals(name, entity);
+ }
+ }
+ }
+ }
+
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig config = new ResourceConfig(Resource.class);
+ config.register(new MetainfServicesBinder(config));
+ return config;
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(new MetainfServicesBinder(config));
+ }
+
+ @Path("/")
+ @Produces("text/plain")
+ @Consumes("text/plain")
+ public static class Resource {
+
+ @GET
+ @Path("{name}")
+ public UselessMessage get(@PathParam("name") final String name) {
+ UselessMessage result = new UselessMessage();
+ result.setMessage("Hello " + name);
+ return result;
+ }
+
+ @POST
+ public String post(final UselessMessage message) {
+ return message.getMessage();
+ }
+
+ } // class Resource
+
+
+ /**
+ * META-INF/services/javax.ws.rs.ext.MessageBodyReader OR META-INF/services/javax.ws.rs.ext.MessageBodyWriter :
+ * org.glassfish.jersey.tests.e2e.server.AbstractDisableMetainfServicesLookupTest$UselessMessageBodyWriter
+ */
+ @Produces("text/plain")
+ @Consumes("text/plain")
+ @Singleton
+ public static class UselessMessageProvider extends AbstractMessageReaderWriterProvider<UselessMessage> {
+
+ public UselessMessageProvider() {
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == UselessMessage.class;
+ }
+
+ @Override
+ public UselessMessage readFrom(
+ Class<UselessMessage> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ return new UselessMessage(readFromAsString(entityStream, mediaType));
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == UselessMessage.class;
+ }
+
+ @Override
+ public long getSize(UselessMessage s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return s.getMessage().length();
+ }
+
+ @Override
+ public void writeTo(
+ UselessMessage t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ writeToAsString(t.getMessage(), entityStream, mediaType);
+ }
+ } // class UselessMessageBodyWriter
+
+
+ public static class UselessMessage {
+
+ private String message;
+
+ public UselessMessage() {
+ }
+
+ public UselessMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return "UselessMessage{"
+ + "message='" + message + '\''
+ + '}';
+ }
+ } // class UselessMessage
+
+ private static class MetainfServicesBinder extends AbstractBinder {
+
+ private final Map<String, Object> properties;
+ private final RuntimeType runtimeType;
+
+ public MetainfServicesBinder(final Configuration config) {
+ this.properties = config.getProperties();
+ this.runtimeType = config.getRuntimeType();
+ }
+
+ @Override
+ protected void configure() {
+ // Message Body providers.
+ install(new ServiceFinderBinder<>(MessageBodyReader.class, properties, runtimeType));
+ install(new ServiceFinderBinder<>(MessageBodyWriter.class, properties, runtimeType));
+ // Exception Mappers.
+ install(new ServiceFinderBinder<>(ExceptionMapper.class, properties, runtimeType));
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AllInjectablesTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AllInjectablesTest.java
new file mode 100644
index 0000000..069b031
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AllInjectablesTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Paul Sandoz
+ */
+public class AllInjectablesTest extends JerseyTest {
+
+ @Path("per-request")
+ public static class PerRequestContextResource {
+ @Context Application app;
+ @Context ResourceContext rc;
+ @Context Configuration config;
+ @Context MessageBodyWorkers mbw;
+ @Context HttpHeaders hs;
+ @Context UriInfo ui;
+ @Context ExtendedUriInfo eui;
+ @Context Request r;
+ @Context SecurityContext sc;
+ @Context Providers p;
+
+ @GET
+ public String get() {
+ assertNotNull(app);
+ assertNotNull(rc);
+ assertNotNull(config);
+ assertNotNull(mbw);
+ assertNotNull(hs);
+ assertNotNull(ui);
+ assertNotNull(eui);
+ assertNotNull(r);
+ assertNotNull(sc);
+ assertNotNull(p);
+ return "GET";
+ }
+ }
+
+ @Path("per-request-constructor")
+ public static class PerRequestContextConstructorParameterResource {
+ public PerRequestContextConstructorParameterResource(@Context final Application app, @Context final ResourceContext rc,
+ @Context final Configuration config, @Context final MessageBodyWorkers mbw, @Context final HttpHeaders hs,
+ @Context final UriInfo ui, @Context final ExtendedUriInfo eui, @Context final Request r,
+ @Context final SecurityContext sc, @Context final Providers p) {
+ assertNotNull(app);
+ assertNotNull(rc);
+ assertNotNull(config);
+ assertNotNull(mbw);
+ assertNotNull(hs);
+ assertNotNull(ui);
+ assertNotNull(eui);
+ assertNotNull(r);
+ assertNotNull(sc);
+ assertNotNull(p);
+ }
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+ }
+
+ @Path("per-request-method")
+ public static class PerRequestContextMethodParameterResource {
+ @GET
+ public String get(@Context final Application app, @Context final ResourceContext rc, @Context final Configuration config,
+ @Context final MessageBodyWorkers mbw, @Context final HttpHeaders hs, @Context final UriInfo ui,
+ @Context final ExtendedUriInfo eui, @Context final Request r, @Context final SecurityContext sc,
+ @Context final Providers p) {
+ assertNotNull(app);
+ assertNotNull(rc);
+ assertNotNull(config);
+ assertNotNull(mbw);
+ assertNotNull(hs);
+ assertNotNull(ui);
+ assertNotNull(eui);
+ assertNotNull(r);
+ assertNotNull(sc);
+ assertNotNull(p);
+ return "GET";
+ }
+ }
+
+ @Path("singleton")
+ @Singleton
+ public static class SingletonContextResource {
+ @Context Application app;
+ @Context ResourceContext rc;
+ @Context Configuration config;
+ @Context MessageBodyWorkers mbw;
+ @Context HttpHeaders hs;
+ @Context UriInfo ui;
+ @Context ExtendedUriInfo eui;
+ @Context Request r;
+ @Context SecurityContext sc;
+ @Context Providers p;
+
+ @GET
+ public String get() {
+ assertNotNull(app);
+ assertNotNull(rc);
+ assertNotNull(config);
+ assertNotNull(mbw);
+ assertNotNull(hs);
+ assertNotNull(ui);
+ assertNotNull(eui);
+ assertNotNull(r);
+ assertNotNull(sc);
+ assertNotNull(p);
+ return "GET";
+ }
+ }
+
+ @Path("singleton-constructor")
+ public static class SingletonContextConstructorParameterResource {
+ public SingletonContextConstructorParameterResource(@Context final Application app, @Context final ResourceContext rc,
+ @Context final Configuration config, @Context final MessageBodyWorkers mbw, @Context final HttpHeaders hs,
+ @Context final UriInfo ui, @Context final ExtendedUriInfo eui, @Context final Request r,
+ @Context final SecurityContext sc, @Context final Providers p) {
+ assertNotNull(app);
+ assertNotNull(rc);
+ assertNotNull(config);
+ assertNotNull(mbw);
+ assertNotNull(hs);
+ assertNotNull(ui);
+ assertNotNull(eui);
+ assertNotNull(r);
+ assertNotNull(sc);
+ assertNotNull(p);
+ }
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+ }
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(PerRequestContextResource.class, PerRequestContextConstructorParameterResource.class,
+ PerRequestContextMethodParameterResource.class, SingletonContextResource.class,
+ SingletonContextConstructorParameterResource.class);
+ }
+
+ @Test
+ public void testPerRequestInjected() throws IOException {
+ assertEquals("GET", target().path("/per-request").request().get(String.class));
+ }
+
+ @Test
+ public void testPerRequestConstructor() throws IOException {
+ assertEquals("GET", target().path("/per-request-constructor").request().get(String.class));
+ }
+
+ @Test
+ public void testPerRequestMethod() throws IOException {
+ assertEquals("GET", target().path("/per-request-method").request().get(String.class));
+ }
+
+ @Test
+ public void testSingleton() throws IOException {
+ assertEquals("GET", target().path("/singleton").request().get(String.class));
+ }
+
+ @Test
+ public void testSingletonConstructor() throws IOException {
+ assertEquals("GET", target().path("/singleton-constructor").request().get(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AmbigousResourceMethodTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AmbigousResourceMethodTest.java
new file mode 100644
index 0000000..9eb249e
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AmbigousResourceMethodTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test of validation of resources as an end-to-end test.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class AmbigousResourceMethodTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Test
+ public void testRequestToAmbiguousResourceClass() {
+ final String simpleName = TestResource.class.getSimpleName();
+
+ Response response = target().path("test").request(MediaType.TEXT_PLAIN).get();
+ assertEquals(200, response.getStatus());
+ assertEquals(simpleName + simpleName, response.readEntity(String.class));
+
+ response = target().path("test").request(MediaType.TEXT_HTML_TYPE).get();
+ assertEquals(200, response.getStatus());
+ assertEquals(simpleName, response.readEntity(String.class));
+
+ response = target().path("test").request(MediaType.TEXT_HTML_TYPE).post(Entity.entity("aaaa", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(simpleName + simpleName, response.readEntity(String.class));
+
+ response = target().path("test").request(MediaType.TEXT_HTML_TYPE).post(Entity.entity("aaaa", MediaType.TEXT_HTML_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(simpleName, response.readEntity(String.class));
+ }
+
+ /**
+ * Test ambiguous resource class.
+ */
+ @Path("test")
+ public static class TestResource {
+ @POST
+ public String sub() {
+ return getClass().getSimpleName();
+ }
+
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String subsub() {
+ return sub() + sub();
+ }
+
+ @GET
+ public String get() {
+ return sub();
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getget() {
+ return subsub();
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest.java
new file mode 100644
index 0000000..6f1df29
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class AppNameBindingTest extends JerseyTest {
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface Global {}
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundRequest {}
+
+ @Global
+ public static class GlobalNameBoundFilter implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok("global", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ @NameBoundRequest
+ @Priority(1)
+ public static class NameBoundRequestFilter implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok("nameBoundRequest", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ @Global
+ public static class MyResourceConfig extends ResourceConfig {
+ public MyResourceConfig() {
+ super(
+ MyResource.class,
+ GlobalNameBoundFilter.class,
+ NameBoundRequestFilter.class
+ );
+ }
+ }
+
+ @Path("/")
+ public static class MyResource {
+ @Path("nameBoundRequest")
+ @GET
+ @NameBoundRequest
+ public String getNameBoundRequest() {
+ return "";
+ }
+
+ @Path("global")
+ @GET
+ public String getPostMatching() {
+ return "";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new MyResourceConfig();
+ }
+
+ @Test
+ public void testNameBoundRequest() {
+ test("nameBoundRequest");
+ }
+
+ @Test
+ public void testGlobal() {
+ test("global");
+ }
+
+ private void test(String name) {
+ Response r = target(name).request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals(name, r.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest2.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest2.java
new file mode 100644
index 0000000..a9e9002
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AppNameBindingTest2.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test {@link NameBinding name binding} annotations on the {@link Application} class.
+ *
+ * @author Miroslav Fuksa
+ */
+public class AppNameBindingTest2 extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApp();
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface FirstGlobalNameBinding {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface SecondGlobalNameBinding {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface ThirdGlobalNameBinding {
+ }
+
+ @Provider
+ @FirstGlobalNameBinding
+ public static class AddOneInterceptor implements
+ WriterInterceptor {
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ String entity = (String) context.getEntity();
+ Integer i = Integer.parseInt(entity);
+ entity = String.valueOf(i + 1);
+ context.setEntity(entity);
+ context.proceed();
+ }
+ }
+
+ @Provider
+ @FirstGlobalNameBinding
+ @SecondGlobalNameBinding
+ public static class AddHundredInterceptor implements
+ WriterInterceptor {
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ String entity = (String) context.getEntity();
+ Integer i = Integer.parseInt(entity);
+ entity = String.valueOf(i + 100);
+ context.setEntity(entity);
+ context.proceed();
+ }
+ }
+
+ @Provider
+ @FirstGlobalNameBinding
+ @SecondGlobalNameBinding
+ @ThirdGlobalNameBinding
+ public static class AddThousandInterceptor implements
+ WriterInterceptor {
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ String entity = (String) context.getEntity();
+ Integer i = Integer.parseInt(entity);
+ entity = String.valueOf(i + 1000);
+ context.setEntity(entity);
+ context.proceed();
+ }
+ }
+
+ @Provider
+ @FirstGlobalNameBinding
+ public static class AddTenFilter implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext,
+ ContainerResponseContext responseContext) throws IOException {
+ String entity = (String) responseContext.getEntity();
+ Integer i = Integer.valueOf(entity);
+ entity = String.valueOf(i + 10);
+ responseContext.setEntity(entity, (Annotation[]) null,
+ MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+
+ @FirstGlobalNameBinding
+ @SecondGlobalNameBinding
+ public class MyApp extends Application {
+
+ public java.util.Set<java.lang.Class<?>> getClasses() {
+ Set<Class<?>> resources = new HashSet<Class<?>>();
+ resources.add(Resource.class);
+ resources.add(AddOneInterceptor.class);
+ resources.add(AddTenFilter.class);
+ resources.add(AddHundredInterceptor.class);
+ resources.add(AddThousandInterceptor.class);
+ return resources;
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @POST
+ @Path("bind")
+ @FirstGlobalNameBinding
+ @ThirdGlobalNameBinding
+ @Produces("text/plain")
+ public String echoWithBind(String echo) {
+ // note: AddThousandInterceptor will not be triggered even we have here @ThirdGlobalNameBinding. Annotations from
+ // Application class and from resource methods are evaluated separately.
+
+ return echo;
+ }
+
+ @POST
+ @Path("nobind")
+ @Produces("text/plain")
+ public String echoNoBind(String echo) {
+ return echo;
+ }
+ }
+
+ @Test
+ public void testBind() {
+ final Response response = target().path("resource/bind").request(MediaType.TEXT_PLAIN_TYPE).post(
+ Entity.entity(Integer.valueOf(0), MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ final Integer integer = response.readEntity(Integer.class);
+ assertEquals(111, integer.intValue());
+ }
+
+
+ @Test
+ public void testNoBind() {
+ final Response response = target().path("resource/nobind").request(MediaType.TEXT_PLAIN_TYPE).post(
+ Entity.entity(Integer.valueOf(0), MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ final Integer integer = response.readEntity(Integer.class);
+ assertEquals(111, integer.intValue());
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncCallbackTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncCallbackTest.java
new file mode 100644
index 0000000..30df036
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncCallbackTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.ConnectionCallback;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.glassfish.jersey.server.ManagedAsync;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ConnectionCallback connection callback}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class AsyncCallbackTest extends JerseyTest {
+
+ public static final AtomicBoolean onDisconnectCalled = new AtomicBoolean(false);
+
+ public static CountDownLatch streamClosedSignal;
+ public static CountDownLatch callbackCalledSignal;
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ @ManagedAsync
+ @Path("outputStream")
+ public void get(@Suspended final AsyncResponse asyncResponse) throws IOException, InterruptedException {
+ asyncResponse.register(MyConnectionCallback.class);
+ final InputStream is = new InputStream() {
+ private int counter = 0;
+
+ @Override
+ public int read() throws IOException {
+ return 65 + (++counter % 35);
+ }
+
+ };
+ asyncResponse.resume(is);
+ }
+
+ @GET
+ @ManagedAsync
+ @Path("chunked")
+ public void getChunkedOutput(@Suspended AsyncResponse asyncResponse) throws IOException, InterruptedException {
+ asyncResponse.register(MyConnectionCallback.class);
+ ChunkedOutput<String> chunkedOutput = new ChunkedOutput<String>(String.class);
+ asyncResponse.resume(chunkedOutput);
+ for (int i = 0; i < 50000; i++) {
+ chunkedOutput.write("something-");
+ }
+ }
+ }
+
+ public static class TestLatch extends CountDownLatch {
+
+ private final String name;
+ private final int multiplier;
+
+ public TestLatch(int count, String name, int multiplier) {
+ super(count);
+ this.name = name;
+ this.multiplier = multiplier;
+ }
+
+ @Override
+ public void countDown() {
+ super.countDown();
+ }
+
+ @Override
+ public void await() throws InterruptedException {
+ final boolean success = super.await(10 * multiplier, TimeUnit.SECONDS);
+ Assert.assertTrue(
+ Thread.currentThread().getName() + ": Latch [" + name + "] awaiting -> timeout!!!",
+ success);
+ }
+ }
+
+ @Before
+ public void setup() {
+ onDisconnectCalled.set(false);
+ streamClosedSignal = new TestLatch(1, "streamClosedSignal", getAsyncTimeoutMultiplier());
+ callbackCalledSignal = new TestLatch(1, "callbackCalledSignal", getAsyncTimeoutMultiplier());
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testOutputStream() throws InterruptedException, IOException {
+ _testConnectionCallback("resource/outputStream");
+ }
+
+ @Test
+ public void testChunkedOutput() throws InterruptedException, IOException {
+ _testConnectionCallback("resource/chunked");
+ }
+
+ private void _testConnectionCallback(String path) throws IOException, InterruptedException {
+ final Response response = target().path(path).request().get();
+ final InputStream inputStream = response.readEntity(InputStream.class);
+ for (int i = 0; i < 500; i++) {
+ inputStream.read();
+ }
+ response.close();
+ streamClosedSignal.countDown();
+ callbackCalledSignal.await();
+ Assert.assertTrue(onDisconnectCalled.get());
+ }
+
+ public static class MyConnectionCallback implements ConnectionCallback {
+
+ @Override
+ public void onDisconnect(AsyncResponse disconnected) {
+ onDisconnectCalled.set(true);
+ callbackCalledSignal.countDown();
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java
new file mode 100644
index 0000000..beaff51
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.server.ManagedAsync;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class AsyncResponseTest extends JerseyTest {
+
+ public static CountDownLatch callbackCalledSignal1;
+ public static CountDownLatch callbackCalledSignal2;
+
+ @Override
+ protected Application configure() {
+ callbackCalledSignal1 = new AsyncCallbackTest.TestLatch(3, "cancel() return value1", getAsyncTimeoutMultiplier());
+ callbackCalledSignal2 = new AsyncCallbackTest.TestLatch(3, "cancel() return value2", getAsyncTimeoutMultiplier());
+
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+
+ return new ResourceConfig(Resource.class, ErrorResource.class, MappedExceptionMapper.class,
+ EntityAnnotationCheckerWriter.class, AsyncMessageBodyProviderResource.class);
+ }
+
+ @Test
+ public void testMultipleCancel() throws InterruptedException, IOException {
+ final Response response = target().path("resource/1").request().get();
+ final InputStream inputStream = response.readEntity(InputStream.class);
+ for (int i = 0; i < 500; i++) {
+ inputStream.read();
+ }
+ response.close();
+ callbackCalledSignal1.await();
+ }
+
+ @Test
+ public void testCancelAfterResume() throws InterruptedException, IOException {
+ final Response response = target().path("resource/2").request().get();
+ final InputStream inputStream = response.readEntity(InputStream.class);
+ for (int i = 0; i < 500; i++) {
+ inputStream.read();
+ }
+ response.close();
+ callbackCalledSignal2.await();
+ }
+
+ @Test
+ public void testResumeWebApplicationException() throws Exception {
+ testResumeException("resumeWebApplicationException", "resumeWebApplicationException");
+ }
+
+ @Test
+ public void testResumeMappedException() throws Exception {
+ testResumeException("resumeMappedException", "resumeMappedException");
+ }
+
+ @Test
+ public void testResumeRuntimeException() throws Exception {
+ testResumeException("resumeRuntimeException", null);
+
+ assertThat(getLastLoggedRecord().getThrown(), instanceOf(RuntimeException.class));
+ }
+
+ @Test
+ public void testResumeCheckedException() throws Exception {
+ testResumeException("resumeCheckedException", null);
+
+ assertThat(getLastLoggedRecord().getThrown(), instanceOf(IOException.class));
+ }
+
+ private void testResumeException(final String path, final String entity) throws Exception {
+ final WebTarget errorResource = target("errorResource");
+
+ final Future<Response> suspended = errorResource.path("suspend").request().async().get();
+ final Response response = errorResource.path(path).request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("ok"));
+
+ final Response suspendedResponse = suspended.get();
+
+ assertThat(suspendedResponse.getStatus(), equalTo(500));
+ if (entity != null) {
+ assertThat(suspendedResponse.readEntity(String.class), equalTo(entity));
+ }
+
+ suspendedResponse.close();
+
+ // Check there is no NPE.
+ for (final LogRecord record : getLoggedRecords()) {
+ final Throwable thrown = record.getThrown();
+ if (thrown != null && thrown instanceof NullPointerException) {
+ fail("Unexpected NPE.");
+ }
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ @Path("1")
+ @ManagedAsync
+ public void get1(@Suspended final AsyncResponse asyncResponse) throws IOException, InterruptedException {
+ if (asyncResponse.cancel()) {
+ callbackCalledSignal1.countDown();
+ }
+ if (asyncResponse.cancel()) {
+ callbackCalledSignal1.countDown();
+ }
+ if (asyncResponse.cancel()) {
+ callbackCalledSignal1.countDown();
+ }
+ }
+
+ @GET
+ @Path("2")
+ @ManagedAsync
+ public void get2(@Suspended final AsyncResponse asyncResponse) throws IOException, InterruptedException {
+ asyncResponse.resume("ok");
+
+ if (!asyncResponse.cancel()) {
+ callbackCalledSignal2.countDown();
+ }
+ if (!asyncResponse.cancel()) {
+ callbackCalledSignal2.countDown();
+ }
+ if (!asyncResponse.cancel()) {
+ callbackCalledSignal2.countDown();
+ }
+ }
+ }
+
+ public static class MappedException extends RuntimeException {
+
+ public MappedException(final String message) {
+ super(message);
+ }
+ }
+
+ public static class MappedExceptionMapper implements ExceptionMapper<MappedException> {
+
+ @Override
+ public Response toResponse(final MappedException exception) {
+ return Response.serverError().entity(exception.getMessage()).build();
+ }
+ }
+
+ @Path("errorResource")
+ public static class ErrorResource {
+
+ private static final BlockingQueue<AsyncResponse> suspended = new ArrayBlockingQueue<AsyncResponse>(1);
+
+ @GET
+ @Path("suspend")
+ public void suspend(@Suspended final AsyncResponse asyncResponse) {
+ suspended.add(asyncResponse);
+ }
+
+ @GET
+ @Path("resumeWebApplicationException")
+ public String resumeWebApplicationException() throws Exception {
+ return resume(new WebApplicationException(Response.serverError().entity("resumeWebApplicationException").build()));
+ }
+
+ @GET
+ @Path("resumeMappedException")
+ public String resumeMappedException() throws Exception {
+ return resume(new MappedException("resumeMappedException"));
+ }
+
+ @GET
+ @Path("resumeRuntimeException")
+ public String resumeRuntimeException() throws Exception {
+ return resume(new RuntimeException("resumeRuntimeException"));
+ }
+
+ @GET
+ @Path("resumeCheckedException")
+ public String resumeCheckedException() throws Exception {
+ return resume(new IOException("resumeCheckedException"));
+ }
+
+ private String resume(final Throwable throwable) throws Exception {
+ return suspended.take().resume(throwable) ? "ok" : "ko";
+ }
+ }
+
+ public static class EntityAnnotationChecker {
+ }
+
+ public static class EntityAnnotationCheckerWriter implements MessageBodyWriter<EntityAnnotationChecker> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final EntityAnnotationChecker entityAnnotationChecker, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final EntityAnnotationChecker entityAnnotationChecker,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+
+ final String entity = annotations.length > 0 ? "ok" : "ko";
+
+ entityStream.write(entity.getBytes());
+ }
+ }
+
+ @Path("annotations")
+ public static class AsyncMessageBodyProviderResource {
+
+ private static final BlockingQueue<AsyncResponse> suspended = new ArrayBlockingQueue<AsyncResponse>(1);
+
+ @GET
+ @Path("suspend")
+ public void suspend(@Suspended final AsyncResponse asyncResponse) {
+ suspended.add(asyncResponse);
+ }
+
+ @GET
+ @Path("suspend-resume")
+ public void suspendResume(@Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new EntityAnnotationChecker());
+ }
+
+ @GET
+ @Path("resume")
+ public String resume() throws Exception {
+ return suspended.take().resume(new EntityAnnotationChecker()) ? "ok" : "ko";
+ }
+ }
+
+ @Test
+ public void testAnnotations() throws Exception {
+ final WebTarget errorResource = target("annotations");
+
+ final Future<Response> suspended = errorResource.path("suspend").request().async().get();
+ final Response response = errorResource.path("resume").request().get();
+ assertThat(response.readEntity(String.class), is("ok"));
+
+ final Response suspendedResponse = suspended.get();
+ assertThat("Entity annotations are not propagated to MBW.", suspendedResponse.readEntity(String.class), is("ok"));
+ suspendedResponse.close();
+ }
+
+ @Test
+ public void testAnnotationsSuspendResume() throws Exception {
+ final Response response = target("annotations").path("suspend-resume").request().async().get().get();
+ assertThat("Entity annotations are not propagated to MBW.", response.readEntity(String.class), is("ok"));
+ response.close();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamExceptionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamExceptionTest.java
new file mode 100644
index 0000000..fa7f371
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamExceptionTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import org.glassfish.jersey.server.ParamException;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Tests the ability to catch WebApplicationException thrown in ParamConverter
+ * used along with BeanParam annotation.
+ *
+ * @author Petr Bouda
+ **/
+public class BeanParamExceptionTest extends JerseyTest {
+
+ private static final String PARAM_NOT_FOUND = "{\"message\":\"This parameter was not found\",\"status\":400}";
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ BeanParamController.class,
+ ModelObjectParamConverter.class,
+ QueryParamErrorMapper.class,
+ JacksonJaxbJsonProvider.class);
+ }
+
+ @Path("/")
+ @Produces("application/json")
+ public static class BeanParamController {
+
+ @GET
+ @Path("/query")
+ public String queryParam(@QueryParam("queryParam") final ModelObject modelObject) {
+ return "Query Param: " + modelObject.toString();
+ }
+
+ @GET
+ @Path("/bean")
+ public String beanParam(@BeanParam final BeanParamObject beanParamObject) {
+ return "Bean Param: " + beanParamObject.getModelObject().toString();
+ }
+
+ }
+
+ @Provider
+ public static class ModelObjectParamConverter implements ParamConverter<ModelObject>, ParamConverterProvider {
+
+ @Override
+ public ModelObject fromString(final String s) {
+ if ("exception".equalsIgnoreCase(s)) {
+ throw new BadParameterException("This parameter was not found");
+ }
+ return new ModelObject(s);
+ }
+
+ @Override
+ public String toString(ModelObject modelObject) {
+ return modelObject.toString();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> ParamConverter<T> getConverter(Class<T> aClass, Type type, Annotation[] annotations) {
+ return aClass.getName().equals(ModelObject.class.getName()) ? (ParamConverter<T>) this : null;
+ }
+
+ }
+
+ @Provider
+ private static class QueryParamErrorMapper implements ExceptionMapper<ParamException.QueryParamException> {
+
+ @Override
+ public Response toResponse(final ParamException.QueryParamException e) {
+ Response.Status status = Response.Status.BAD_REQUEST;
+ final Throwable cause = e.getCause();
+ if (cause instanceof BadParameterException) {
+ return Response.status(status).entity(new ErrorMessage(status.getStatusCode(), cause.getMessage())).build();
+ }
+ return null;
+ }
+ }
+
+ @Test
+ public void testMarshallExceptionQuery() {
+ Response response = target().path("query").queryParam("queryParam", "exception")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ assertEquals(400, response.getStatus());
+ assertEquals(PARAM_NOT_FOUND, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testMarshallExceptionBean() {
+ Response response = target().path("bean").queryParam("queryParam", "exception")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ assertEquals(400, response.getStatus());
+ assertEquals(PARAM_NOT_FOUND, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testMarshallModelQuery() {
+ Response response = target().path("query").queryParam("queryParam", "model")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("Query Param: model", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testMarshallModelBean() {
+ Response response = target().path("bean").queryParam("queryParam", "model")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("Bean Param: model", response.readEntity(String.class));
+ }
+
+ private static class BadParameterException extends RuntimeException {
+
+ public BadParameterException(final String s) {
+ super(s);
+ }
+ }
+
+ public static class BeanParamObject {
+
+ final ModelObject modelObject;
+
+ public BeanParamObject(@QueryParam("queryParam") final ModelObject modelObject) {
+ this.modelObject = modelObject;
+ }
+
+ public ModelObject getModelObject() {
+ return modelObject;
+ }
+ }
+
+ public static class ModelObject {
+
+ private final String privateData;
+
+ public ModelObject(final String privateData) {
+ this.privateData = privateData;
+ }
+
+ @Override
+ public String toString() {
+ return privateData;
+ }
+ }
+
+ public static class ErrorMessage {
+
+ private final String message;
+
+ private final int status;
+
+ public ErrorMessage(final int status, final String message) {
+ this.message = message;
+ this.status = status;
+ }
+
+ @JsonProperty
+ public String getMessage() {
+ return message;
+ }
+
+ @JsonProperty
+ public int getStatus() {
+ return status;
+ }
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamTest.java
new file mode 100644
index 0000000..cb72b3f
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BeanParamTest.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.Arrays;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests {@link BeanParam bean param injections}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class BeanParamTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class,
+ ResourceInitializedBySetter.class);
+ }
+
+ @Test
+ public void compareBeanWithStandardParams() {
+ FullBean bean = getFullBean();
+ Response response = doRequest(bean, "resource/compareBean");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("true", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testSingleFullBean() {
+ FullBean bean = getFullBean();
+ Response response = doRequest(bean, "resource/singleBean");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(bean.toString(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testSingleConstructorInitializedBean() {
+ FullBean bean = getFullBean();
+ Response response = doRequest(bean, "resource/constructorBean");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(bean.toString(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testTwoFullBeans() {
+ FullBean bean = getFullBean();
+ Response response = doRequest(bean, "resource/twoBeans");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(bean.toString() + " / " + bean.toString(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testTwoDifferentBeans() {
+ FullBean fullBean = getFullBean();
+ SmallBean smallBean = new SmallBean(fullBean);
+ Response response = doRequest(fullBean, "resource/differentBeans");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(fullBean.toString() + " / " + smallBean.toString(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testEncodedBean() {
+ FullBean fullBean = getFullBean();
+ fullBean.setQueryParam("encoded/a?&&+./?");
+ fullBean.setMatrixParam("not-encoded/a?&&+./?");
+
+ Response response = doRequest(fullBean, "resource/encodedBean");
+ Assert.assertEquals(200, response.getStatus());
+
+ EncodedBean bean = new EncodedBean("not-encoded/a?&&+./?", "encoded%2Fa%3F%26%26%2B.%2F%3F");
+ Assert.assertEquals(bean.toString(), response.readEntity(String.class));
+ }
+
+ private Response doRequest(FullBean bean, String path) {
+ final Form form = new Form();
+ form.asMap().put("form", Arrays.asList(bean.getFormParam()));
+
+ return target().path(path).path(bean.getPathParam()).matrixParam("matrix",
+ bean.getMatrixParam()).queryParam("query",
+ bean.getQueryParam()).request().header("header", bean.getHeaderParam()).cookie("cookie",
+ bean.getCookie()).post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ }
+
+ private FullBean getFullBean() {
+ FullBean bean = new FullBean();
+ bean.setPathParam("pathParameter");
+ bean.setMatrixParam("matrixParameter");
+ bean.setQueryParam("queryParameter");
+ bean.setHeaderParam("headerParameter");
+ bean.setCookie("cookieParameter");
+ bean.setFormParam("formParameter");
+ bean.setOverrideRequestNull(true);
+ return bean;
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @POST
+ @Path("singleBean/{path}")
+ public String postBeanParam(@BeanParam FullBean bean) {
+ return bean == null ? "fail: bean param is null!!!" : bean.toString();
+ }
+
+ @POST
+ @Path("constructorBean/{path}")
+ public String constructorBeanParam(@BeanParam ConstructorInitializedBean bean) {
+ return bean == null ? "fail: bean param is null!!!" : bean.toString();
+ }
+
+ @POST
+ @Path("compareBean/{path}")
+ public String compareBeanParam(@BeanParam ConstructorInitializedBean bean, @CookieParam("cookie") String cookie,
+ @FormParam("form") String formParam,
+ @HeaderParam("header") String headerParam, @MatrixParam("matrix") String matrixParam,
+ @QueryParam("query") String queryParam, @PathParam("path") String pathParam,
+ @Context Request request) {
+ ConstructorInitializedBean newBean = new ConstructorInitializedBean(cookie, formParam,
+ headerParam, matrixParam,
+ queryParam, pathParam, request);
+
+ return String.valueOf(bean.toString().equals(newBean.toString()));
+ }
+
+ @POST
+ @Path("twoBeans/{path}")
+ public String postTwoSameBeans(@BeanParam FullBean bean1, @BeanParam FullBean bean2) {
+ if (bean1 == null) {
+ return "fail: bean1 param is null!!!";
+ }
+ if (bean2 == null) {
+ return "fail: bean2 param is null!!!";
+ }
+ return bean1.toString() + " / " + bean2.toString();
+ }
+
+ @POST
+ @Path("differentBeans/{path}")
+ public String postTwoDifferentBeans(@BeanParam FullBean bean1, @BeanParam SmallBean bean2) {
+ if (bean1 == null) {
+ return "fail: bean1 param is null!!!";
+ }
+ if (bean2 == null) {
+ return "fail: bean2 param is null!!!";
+ }
+ return bean1.toString() + " / " + bean2.toString();
+ }
+
+ @POST
+ @Path("encodedBean/{path}")
+ public String postEncodedParam(@BeanParam EncodedBean bean) {
+ return bean == null ? "fail: bean param is null!!!" : bean.toString();
+ }
+
+ }
+
+ public static class SmallBean {
+
+ @HeaderParam("header")
+ private String headerParam;
+
+ @PathParam("path")
+ private String pathParam;
+
+ public SmallBean(FullBean bean) {
+ headerParam = bean.getHeaderParam();
+ pathParam = bean.getPathParam();
+ }
+
+ public SmallBean() {
+ }
+
+ @Override
+ public String toString() {
+ return "SmallBean{"
+ + "headerParam='" + headerParam + '\''
+ + ", pathParam='" + pathParam + '\''
+ + '}';
+ }
+ }
+
+ public static class EncodedBean {
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @Encoded
+ @QueryParam("query")
+ private String queryParam;
+
+ public EncodedBean(String matrixParam, String queryParam) {
+ this.matrixParam = matrixParam;
+ this.queryParam = queryParam;
+ }
+
+ public EncodedBean() {
+ }
+
+ @Override
+ public String toString() {
+ return "EncodedBean{"
+ + "matrixParam='" + matrixParam + '\''
+ + ", queryParam='" + queryParam + '\''
+ + '}';
+ }
+ }
+
+ public static class FullBean {
+
+ @HeaderParam("header")
+ private String headerParam;
+
+ @PathParam("path")
+ private String pathParam;
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @QueryParam("query")
+ private String queryParam;
+
+ @CookieParam("cookie")
+ private String cookie;
+
+ @FormParam("form")
+ private String formParam;
+
+ @Context
+ private Request request;
+
+ private boolean overrideRequestNull;
+
+ public FullBean() {
+ }
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public void setCookie(String cookie) {
+ this.cookie = cookie;
+ }
+
+ public String getFormParam() {
+ return formParam;
+ }
+
+ public void setFormParam(String formParam) {
+ this.formParam = formParam;
+ }
+
+ public String getHeaderParam() {
+ return headerParam;
+ }
+
+ public void setHeaderParam(String headerParam) {
+ this.headerParam = headerParam;
+ }
+
+ public String getMatrixParam() {
+ return matrixParam;
+ }
+
+ public void setMatrixParam(String matrixParam) {
+ this.matrixParam = matrixParam;
+ }
+
+ public String getPathParam() {
+ return pathParam;
+ }
+
+ public void setPathParam(String pathParam) {
+ this.pathParam = pathParam;
+ }
+
+ public String getQueryParam() {
+ return queryParam;
+ }
+
+ public void setQueryParam(String queryParam) {
+ this.queryParam = queryParam;
+ }
+
+ public Request getRequest() {
+ return request;
+ }
+
+ public void setRequest(Request request) {
+ this.request = request;
+ }
+
+ public boolean isOverrideRequestNull() {
+ return overrideRequestNull;
+ }
+
+ public void setOverrideRequestNull(boolean overrideRequestNull) {
+ this.overrideRequestNull = overrideRequestNull;
+ }
+
+ private String requestToString() {
+ if (overrideRequestNull) {
+ return "not-null";
+ } else {
+ return request == null ? "null" : "not-null";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Bean{"
+ + "cookie='" + cookie + '\''
+ + ", formParam='" + formParam + '\''
+ + ", headerParam='" + headerParam + '\''
+ + ", matrixParam='" + matrixParam + '\''
+ + ", pathParam='" + pathParam + '\''
+ + ", queryParam='" + queryParam + '\''
+ + ", request='" + requestToString() + "'"
+ + '}';
+ }
+ }
+
+ public static class ConstructorInitializedBean {
+
+ private String headerParam;
+ private String pathParam;
+ private String matrixParam;
+ private String queryParam;
+ private String cookie;
+ private String formParam;
+ private Request request;
+
+ public ConstructorInitializedBean(@CookieParam("cookie") String cookie, @FormParam("form") String formParam,
+ @HeaderParam("header") String headerParam, @MatrixParam("matrix") String matrixParam,
+ @QueryParam("query") String queryParam, @PathParam("path") String pathParam,
+ @Context Request request) {
+ this.cookie = cookie;
+ this.formParam = formParam;
+ this.headerParam = headerParam;
+ this.matrixParam = matrixParam;
+ this.queryParam = queryParam;
+ this.pathParam = pathParam;
+ this.request = request;
+ }
+
+ private boolean overrideRequestNull;
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public void setCookie(String cookie) {
+ this.cookie = cookie;
+ }
+
+ public String getFormParam() {
+ return formParam;
+ }
+
+ public void setFormParam(String formParam) {
+ this.formParam = formParam;
+ }
+
+ public String getHeaderParam() {
+ return headerParam;
+ }
+
+ public void setHeaderParam(String headerParam) {
+ this.headerParam = headerParam;
+ }
+
+ public String getMatrixParam() {
+ return matrixParam;
+ }
+
+ public void setMatrixParam(String matrixParam) {
+ this.matrixParam = matrixParam;
+ }
+
+ public String getPathParam() {
+ return pathParam;
+ }
+
+ public void setPathParam(String pathParam) {
+ this.pathParam = pathParam;
+ }
+
+ public String getQueryParam() {
+ return queryParam;
+ }
+
+ public void setQueryParam(String queryParam) {
+ this.queryParam = queryParam;
+ }
+
+ public Request getRequest() {
+ return request;
+ }
+
+ public void setRequest(Request request) {
+ this.request = request;
+ }
+
+ public boolean isOverrideRequestNull() {
+ return overrideRequestNull;
+ }
+
+ public void setOverrideRequestNull(boolean overrideRequestNull) {
+ this.overrideRequestNull = overrideRequestNull;
+ }
+
+ private String requestToString() {
+ if (overrideRequestNull) {
+ return "not-null";
+ } else {
+ return request == null ? "null" : "not-null";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Bean{"
+ + "cookie='" + cookie + '\''
+ + ", formParam='" + formParam + '\''
+ + ", headerParam='" + headerParam + '\''
+ + ", matrixParam='" + matrixParam + '\''
+ + ", pathParam='" + pathParam + '\''
+ + ", queryParam='" + queryParam + '\''
+ + ", request='" + requestToString() + "'"
+ + '}';
+ }
+ }
+
+ @Path("resource-setter")
+ public static class ResourceInitializedBySetter {
+
+ private FullBean fullBean;
+
+ @BeanParam
+ public void setFullBean(FullBean fullBean) {
+ this.fullBean = fullBean;
+ }
+
+ @POST
+ @Path("{path}")
+ public String post() {
+ return fullBean.toString();
+ }
+ }
+
+ @Test
+ public void testResourceInitializedBySetter() {
+ FullBean bean = getFullBean();
+ final Response response = doRequest(bean, "resource-setter");
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(bean.toString(), response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BroadcasterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BroadcasterTest.java
new file mode 100644
index 0000000..9a967cc
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/BroadcasterTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.Broadcaster;
+import org.glassfish.jersey.server.BroadcasterListener;
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class BroadcasterTest extends JerseyTest {
+ static Broadcaster<String> broadcaster = new Broadcaster<String>() {
+ @Override
+ public void onClose(ChunkedOutput<String> stringChunkedOutput) {
+ closedOutputs.add(stringChunkedOutput);
+ }
+ };
+
+ static List<ChunkedOutput<String>> outputs = new ArrayList<>();
+ static List<ChunkedOutput<String>> closedOutputs = new ArrayList<>();
+ static int listenerClosed = 0;
+
+ @Path("/test")
+ public static class MyResource {
+ @GET
+ public ChunkedOutput<String> get() {
+ ChunkedOutput<String> result = new ChunkedOutput<String>() {};
+
+ // write something to ensure the client does not get blocked on waiting for the first byte
+ try {
+ result.write("firstChunk");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ outputs.add(result);
+ broadcaster.add(result);
+ return result;
+ }
+
+ @POST
+ public String post(String text) {
+ broadcaster.broadcast(text);
+ return text;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class);
+ }
+
+ @Test
+ public void testBroadcaster() throws IOException {
+ InputStream is1 = getChunkStream();
+ InputStream is2 = getChunkStream();
+ InputStream is3 = getChunkStream();
+ InputStream is4 = getChunkStream();
+
+ target("test").request().post(Entity.text("text1"));
+ checkClosed(0);
+ checkStream("firstChunktext1", is1, is2, is3, is4);
+
+ outputs.remove(0).close();
+
+ target("test").request().post(Entity.text("text2"));
+ checkStream("text2", is2, is3, is4);
+ checkClosed(1);
+
+ outputs.remove(0).close();
+
+ BroadcasterListener<String> bl = new BroadcasterListener<String>() {
+ @Override
+ public void onException(ChunkedOutput<String> stringChunkedResponse, Exception exception) {
+ }
+
+ @Override
+ public void onClose(ChunkedOutput<String> stringChunkedResponse) {
+ listenerClosed++;
+ }
+ };
+
+ broadcaster.add(bl);
+
+ target("test").request().post(Entity.text("text3"));
+ checkClosed(2);
+ assertEquals(1, listenerClosed);
+
+ broadcaster.remove(bl);
+ broadcaster.closeAll();
+
+ checkClosed(4);
+ assertEquals(1, listenerClosed);
+
+ checkStream("text3", is3, is4);
+ }
+
+ private InputStream getChunkStream() {
+ return target("test").request().get(InputStream.class);
+ }
+
+ private void checkStream(String golden, InputStream... inputStreams) throws IOException {
+ byte[] bytes = golden.getBytes();
+ byte[] entity = new byte[bytes.length];
+ for (InputStream is : inputStreams) {
+ int bytesRead = 0;
+ int previous = 0;
+ while ((bytesRead += is.read(entity, bytesRead, entity.length - bytesRead)) < entity.length
+ && previous != bytesRead) {
+ previous = bytesRead;
+ }
+ assertEquals(golden, new String(entity));
+ }
+ }
+
+ private void checkClosed(int count) {
+ assertEquals("Closed count does not match", count, closedOutputs.size());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java
new file mode 100644
index 0000000..29aec13
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.client.ChunkedInput;
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Chunked input/output tests.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ChunkedInputOutputTest extends JerseyTest {
+ private static final Logger LOGGER = Logger.getLogger(ChunkedInputOutputTest.class.getName());
+
+ /**
+ * Test resource.
+ */
+ @Path("/test")
+ public static class TestResource {
+ /**
+ * Get chunk stream.
+ *
+ * @return chunk stream.
+ */
+ @GET
+ public ChunkedOutput<String> get() {
+ final ChunkedOutput<String> output = new ChunkedOutput<>(String.class, "\r\n");
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ output.write("test");
+ output.write("test");
+ output.write("test");
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, "Error writing chunk.", e);
+ } finally {
+ try {
+ output.close();
+ } catch (final IOException e) {
+ LOGGER.log(Level.INFO, "Error closing chunked output.", e);
+ }
+ }
+ }
+ }.start();
+
+ return output;
+ }
+
+ /**
+ * Get chunk stream with an attached interceptor.
+ *
+ * @return intercepted chunk stream.
+ */
+ @GET
+ @Path("intercepted")
+ @Intercepted
+ public ChunkedOutput<String> interceptedGet() {
+ return get();
+ }
+ }
+
+ /**
+ * Test interceptor binding.
+ */
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface Intercepted {
+
+ }
+
+ /**
+ * Test interceptor - counts number of interception as well as number of wrapper output stream method calls.
+ */
+ @Intercepted
+ public static class TestWriterInterceptor implements WriterInterceptor {
+
+ private static final AtomicInteger interceptCounter = new AtomicInteger(0);
+ private static final AtomicInteger writeCounter = new AtomicInteger(0);
+ private static final AtomicInteger flushCounter = new AtomicInteger(0);
+ private static final AtomicInteger closeCounter = new AtomicInteger(0);
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ interceptCounter.incrementAndGet();
+ final OutputStream out = context.getOutputStream();
+ context.setOutputStream(new OutputStream() {
+ @Override
+ public void write(final int b) throws IOException {
+ writeCounter.incrementAndGet();
+ out.write(b);
+ }
+
+ @Override
+ public void write(final byte[] b) throws IOException {
+ writeCounter.incrementAndGet();
+ out.write(b);
+ }
+
+ @Override
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ writeCounter.incrementAndGet();
+ out.write(b, off, len);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ flushCounter.incrementAndGet();
+ out.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ closeCounter.incrementAndGet();
+ out.close();
+ }
+ });
+ context.proceed();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class, TestWriterInterceptor.class);
+ }
+
+ /**
+ * Test retrieving chunked response stream as a single response string.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testChunkedOutputToSingleString() throws Exception {
+ final String response = target().path("test").request().get(String.class);
+
+ assertEquals("Unexpected value of chunked response unmarshalled as a single string.",
+ "test\r\ntest\r\ntest\r\n", response);
+ }
+
+ /**
+ * Test retrieving chunked response stream sequentially as individual chunks using chunked input.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testChunkedOutputToChunkInput() throws Exception {
+ final ChunkedInput<String> input = target().path("test").request().get(new GenericType<ChunkedInput<String>>() {
+ });
+
+ int counter = 0;
+ String chunk;
+ while ((chunk = input.read()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, "test", chunk);
+ counter++;
+ }
+
+ assertEquals("Unexpected numbed of received chunks.", 3, counter);
+ }
+
+ /**
+ * Test retrieving intercepted chunked response stream sequentially as individual chunks using chunked input.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testInterceptedChunkedOutputToChunkInput() throws Exception {
+ final ChunkedInput<String> input = target().path("test/intercepted")
+ .request().get(new GenericType<ChunkedInput<String>>() {
+ });
+
+ int counter = 0;
+ String chunk;
+ while ((chunk = input.read()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, "test", chunk);
+ counter++;
+ }
+
+ assertThat("Unexpected numbed of received chunks.",
+ counter, equalTo(3));
+
+ assertThat("Unexpected number of chunked output interceptions.",
+ TestWriterInterceptor.interceptCounter.get(), equalTo(1));
+ assertThat("Unexpected number of intercepted output write calls.",
+ TestWriterInterceptor.writeCounter.get(), greaterThanOrEqualTo(1));
+ assertThat("Unexpected number of intercepted output flush calls.",
+ TestWriterInterceptor.flushCounter.get(), greaterThanOrEqualTo(3));
+ assertThat("Unexpected number of intercepted output close calls.",
+ TestWriterInterceptor.closeCounter.get(), equalTo(1));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ClientResponseOnServerTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ClientResponseOnServerTest.java
new file mode 100644
index 0000000..2642876
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ClientResponseOnServerTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for support of client-side response in the server-side resource implementation.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ClientResponseOnServerTest extends JerseyTest {
+
+ @Path("root")
+ public static class RootResource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("response")
+ public Response getResponse(@Uri("internal/response") WebTarget target) {
+ // returns client-side response instance
+ return target.request(MediaType.TEXT_PLAIN).get();
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("error")
+ public String getError(@Uri("internal/error") WebTarget target) {
+ // throws WebApplicationException with an error response
+ return target.request(MediaType.TEXT_PLAIN).get(String.class);
+ }
+ }
+
+ @Path("internal")
+ public static class InternalResource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("response")
+ public String getResponse() {
+ return "response";
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("error")
+ public Response getError() {
+ // Testing for a cross-stack support of a completely custom status code.
+ return Response.status(699).type(MediaType.TEXT_PLAIN).entity("error").build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ RootResource.class,
+ InternalResource.class
+ );
+ }
+
+ @Test
+ public void testClientResponseUsageOnServer() {
+ final WebTarget target = target("root/{type}");
+
+ Response response;
+
+ response = target.resolveTemplate("type", "response").request(MediaType.TEXT_PLAIN).get();
+ assertEquals(200, response.getStatus());
+ assertEquals("response", response.readEntity(String.class));
+
+ response = target.resolveTemplate("type", "error").request(MediaType.TEXT_PLAIN).get();
+ assertEquals(699, response.getStatus());
+ assertEquals("error", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CloseableTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CloseableTest.java
new file mode 100644
index 0000000..89bf38d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CloseableTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.CloseableService;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marc Hadley
+ */
+public class CloseableTest extends JerseyTest {
+ private static CountDownLatch perRequestCdl = new CountDownLatch(1);
+ private static CountDownLatch singletonCdl = new CountDownLatch(1);
+
+ @Path("per-request")
+ public static class PerRequestResource implements Closeable {
+ static boolean isClosed;
+
+ @Context
+ CloseableService cs;
+
+ @GET
+ public String doGet() {
+ isClosed = false;
+ cs.add(this);
+ return "ok";
+ }
+
+ public void close() throws IOException {
+ isClosed = true;
+ perRequestCdl.countDown();
+ }
+ }
+
+ @Path("singleton")
+ @Singleton
+ public static class SingletonResource extends PerRequestResource {
+ @Override
+ public void close() {
+ isClosed = true;
+ singletonCdl.countDown();
+ }
+ }
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(PerRequestResource.class, SingletonResource.class);
+ }
+
+ @Test
+ public void testPerRequest() throws InterruptedException {
+ target().path("per-request").request().get(String.class);
+ perRequestCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertTrue(PerRequestResource.isClosed);
+ }
+
+ @Test
+ public void testSingleton() throws InterruptedException {
+ target().path("singleton").request().get(String.class);
+ perRequestCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertTrue(SingletonResource.isClosed);
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
new file mode 100644
index 0000000..c1ce740
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class CompletionStageTest extends JerseyTest {
+
+ static final String ENTITY = "entity";
+ // delay of async operations in seconds.
+ static final int DELAY = 1;
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(CompletionStageResource.class);
+ }
+
+ @Test
+ public void testGetCompleted() {
+ Response response = target("cs/completed").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ENTITY));
+ }
+
+ @Test
+ public void testGetException400() {
+ Response response = target("cs/exception400").request().get();
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+ @Test
+ public void testGetException405() {
+ Response response = target("cs/exception405").request().get();
+
+ assertThat(response.getStatus(), is(405));
+ }
+
+ @Test
+ public void testGetCancelled() {
+ Response response = target("cs/cancelled").request().get();
+
+ assertThat(response.getStatus(), is(503));
+ }
+
+ @Test
+ public void testGetCompletedAsync() {
+ Response response = target("cs/completedAsync").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ENTITY));
+ }
+
+ @Test
+ public void testGetException400Async() {
+ Response response = target("cs/exception400Async").request().get();
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+ @Test
+ public void testGetException405Async() {
+ Response response = target("cs/exception405Async").request().get();
+
+ assertThat(response.getStatus(), is(405));
+ }
+
+ @Test
+ public void testGetCancelledAsync() {
+ Response response = target("cs/cancelledAsync").request().get();
+
+ assertThat(response.getStatus(), is(503));
+ }
+
+ @Test
+ public void testGetCustomCompleted() {
+ Response response = target("cs/custom").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ENTITY));
+ }
+
+ @Test
+ public void testGetCustomAsync() {
+ Response response = target("cs/customAsync").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ENTITY));
+ }
+
+ @Path("/cs")
+ public static class CompletionStageResource {
+
+ private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool();
+
+ @GET
+ @Path("/completed")
+ public CompletionStage<String> getCompleted() {
+ return CompletableFuture.completedFuture(ENTITY);
+ }
+
+ @GET
+ @Path("/exception400")
+ public CompletionStage<String> getException400() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ cs.completeExceptionally(new WebApplicationException(400));
+
+ return cs;
+ }
+
+ @GET
+ @Path("/exception405")
+ public CompletionStage<String> getException405() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ cs.completeExceptionally(new WebApplicationException(405));
+
+ return cs;
+ }
+
+ @GET
+ @Path("/cancelled")
+ public CompletionStage<String> getCancelled() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ cs.cancel(true);
+
+ return cs;
+ }
+
+ @GET
+ @Path("/completedAsync")
+ public CompletionStage<String> getCompletedAsync() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ delaySubmit(() -> cs.complete(ENTITY));
+ return cs;
+ }
+
+ @GET
+ @Path("/exception400Async")
+ public CompletionStage<String> getException400Async() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ delaySubmit(() -> cs.completeExceptionally(new WebApplicationException(400)));
+
+ return cs;
+ }
+
+ @GET
+ @Path("/exception405Async")
+ public CompletionStage<String> getException405Async() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ delaySubmit(() -> cs.completeExceptionally(new WebApplicationException(405)));
+
+ return cs;
+ }
+
+ @GET
+ @Path("/cancelledAsync")
+ public CompletionStage<String> getCancelledAsync() {
+ CompletableFuture<String> cs = new CompletableFuture<>();
+ delaySubmit(() -> cs.cancel(true));
+
+ return cs;
+ }
+
+ /**
+ * Return completed CompletionStage which doesn't support #toCompletableFuture().
+ *
+ * @return CompletionStage which doesn't support #toCompletableFuture().
+ */
+ @GET
+ @Path("/custom")
+ public CompletionStage<String> getCustomCompletionStage() {
+ return new CustomCompletionStage<>(CompletableFuture.completedFuture(ENTITY));
+ }
+
+ /**
+ * Return uncompleted CompletionStage which doesn't support #toCompletableFuture().
+ *
+ * @return CompletionStage which doesn't support #toCompletableFuture().
+ */
+ @GET
+ @Path("/customAsync")
+ public CompletionStage<String> getCustomCompletionStageAsync() {
+ CompletableFuture<String> cf = new CompletableFuture<>();
+ CustomCompletionStage<String> cs = new CustomCompletionStage<>(cf);
+ delaySubmit(() -> cf.complete(ENTITY));
+
+ return cs;
+ }
+
+ private void delaySubmit(Runnable runnable) {
+ EXECUTOR_SERVICE.submit(() -> {
+ try {
+ Thread.sleep(DELAY * 1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ runnable.run();
+ });
+ }
+ }
+
+ private static class CustomCompletionStage<T> implements CompletionStage<T> {
+
+ private final CompletionStage<T> completedFuture;
+
+ CustomCompletionStage(CompletionStage<T> completedFuture) {
+ this.completedFuture = completedFuture;
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenApply(Function<? super T, ? extends U> fn) {
+ return completedFuture.thenApply(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenApplyAsync(Function<? super T, ? extends U> fn) {
+ return completedFuture.thenApplyAsync(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenApplyAsync(Function<? super T, ? extends U> fn, Executor executor) {
+ return completedFuture.thenApplyAsync(fn, executor);
+ }
+
+ @Override
+ public CompletionStage<Void> thenAccept(Consumer<? super T> action) {
+ return completedFuture.thenAccept(action);
+ }
+
+ @Override
+ public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action) {
+ return completedFuture.thenAcceptAsync(action);
+ }
+
+ @Override
+ public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor) {
+ return completedFuture.thenAcceptAsync(action, executor);
+ }
+
+ @Override
+ public CompletionStage<Void> thenRun(Runnable action) {
+ return completedFuture.thenRun(action);
+ }
+
+ @Override
+ public CompletionStage<Void> thenRunAsync(Runnable action) {
+ return completedFuture.thenRunAsync(action);
+ }
+
+ @Override
+ public CompletionStage<Void> thenRunAsync(Runnable action, Executor executor) {
+ return completedFuture.thenRunAsync(action, executor);
+ }
+
+ @Override
+ public <U, V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,
+ BiFunction<? super T, ? super U, ? extends V> fn) {
+ return completedFuture.thenCombine(other, fn);
+ }
+
+ @Override
+ public <U, V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
+ BiFunction<? super T, ? super U, ? extends V> fn) {
+ return completedFuture.thenCombineAsync(other, fn);
+ }
+
+ @Override
+ public <U, V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
+ BiFunction<? super T, ? super U, ? extends V> fn, Executor executor) {
+ return completedFuture.thenCombineAsync(other, fn, executor);
+ }
+
+ @Override
+ public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action) {
+ return completedFuture.thenAcceptBoth(other, action);
+ }
+
+ @Override
+ public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action) {
+ return completedFuture.thenAcceptBothAsync(other, action);
+ }
+
+ @Override
+ public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action, Executor executor) {
+ return completedFuture.thenAcceptBothAsync(other, action, executor);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, Runnable action) {
+ return completedFuture.runAfterBoth(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action) {
+ return completedFuture.runAfterBothAsync(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor) {
+ return completedFuture.runAfterBothAsync(other, action, executor);
+ }
+
+ @Override
+ public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn) {
+ return completedFuture.applyToEither(other, fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn) {
+ return completedFuture.applyToEitherAsync(other, fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,
+ Function<? super T, U> fn,
+ Executor executor) {
+ return completedFuture.applyToEitherAsync(other, fn, executor);
+ }
+
+ @Override
+ public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action) {
+ return completedFuture.acceptEither(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action) {
+ return completedFuture.acceptEitherAsync(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,
+ Consumer<? super T> action,
+ Executor executor) {
+ return completedFuture.acceptEitherAsync(other, action, executor);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterEither(CompletionStage<?> other, Runnable action) {
+ return completedFuture.runAfterEither(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action) {
+ return completedFuture.runAfterEitherAsync(other, action);
+ }
+
+ @Override
+ public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action, Executor executor) {
+ return completedFuture.runAfterEitherAsync(other, action, executor);
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn) {
+ return completedFuture.thenCompose(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) {
+ return completedFuture.thenComposeAsync(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,
+ Executor executor) {
+ return completedFuture.thenComposeAsync(fn, executor);
+ }
+
+ @Override
+ public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn) {
+ return completedFuture.exceptionally(fn);
+ }
+
+ @Override
+ public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
+ return completedFuture.whenComplete(action);
+ }
+
+ @Override
+ public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) {
+ return completedFuture.whenCompleteAsync(action);
+ }
+
+ @Override
+ public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor) {
+ return completedFuture.whenCompleteAsync(action, executor);
+ }
+
+ @Override
+ public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) {
+ return completedFuture.handle(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn) {
+ return completedFuture.handleAsync(fn);
+ }
+
+ @Override
+ public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
+ return completedFuture.handleAsync(fn, executor);
+ }
+
+ @Override
+ public CompletableFuture<T> toCompletableFuture() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContainerListenerRegistrationAsProvidersTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContainerListenerRegistrationAsProvidersTest.java
new file mode 100644
index 0000000..bc46bee
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContainerListenerRegistrationAsProvidersTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ContainerListenerRegistrationAsProvidersTest extends JerseyTest {
+
+ MyListener listener;
+
+ @Override
+ public ResourceConfig configure() {
+ listener = new MyListener();
+ final ResourceConfig result = new ResourceConfig(One.class, YetAnotherListener.class).registerInstances(listener);
+ return result;
+ }
+
+ static class YetAnotherListener extends AbstractContainerLifecycleListener {
+
+ static boolean started;
+
+ @Override
+ public void onStartup(Container container) {
+ started = true;
+ }
+ }
+
+ static class MyListener extends AbstractContainerLifecycleListener {
+
+ boolean startupInvoked;
+
+ @Override
+ public void onStartup(Container container) {
+ startupInvoked = true;
+ }
+ }
+
+ @Test
+ public void testListener() {
+ assertEquals("whatever", target().path("doesNotMatter").request().get().readEntity(String.class));
+ assertTrue(listener.startupInvoked);
+ assertTrue(YetAnotherListener.started);
+ }
+
+ @Path("doesNotMatter")
+ public static class One {
+ @GET
+ public String get() {
+ return "whatever";
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContentNegotiationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContentNegotiationTest.java
new file mode 100644
index 0000000..77732c7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ContentNegotiationTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.internal.HttpUrlConnector;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests determining media type of the response (especially that qs quality parameter is respected when
+ * more media types are defined on the resource method).
+ *
+ * @author Miroslav Fuksa
+ */
+public class ContentNegotiationTest extends JerseyTest {
+
+ @Path("persons")
+ public static class MyResource {
+ private static final Person[] LIST = new Person[] {
+ new Person("Penny", 1),
+ new Person("Howard", 2),
+ new Person("Sheldon", 3)
+ };
+
+ @GET
+ @Produces({"application/xml;qs=0.75", "application/json;qs=1.0"})
+ public Person[] getList() {
+ return LIST;
+ }
+
+ @GET
+ @Produces({"application/json;qs=1", "application/xml;qs=0.75"})
+ @Path("reordered")
+ public Person[] getListReordered() {
+ return LIST;
+ }
+
+ @GET
+ @Produces({"application/json;qs=0.75", "application/xml;qs=1"})
+ @Path("inverted")
+ public Person[] getListInverted() {
+ return LIST;
+ }
+
+
+ @GET
+ @Produces({"application/xml;qs=0.75", "application/json;qs=0.9", "unknown/hello;qs=1.0"})
+ @Path("unkownMT")
+ public Person[] getListWithUnkownType() {
+ return LIST;
+ }
+
+ @GET
+ @Produces({"application/json", "application/xml", "text/plain"})
+ @Path("shouldPickFirstJson")
+ public Person[] getJsonArrayUnlessOtherwiseSpecified() {
+ return LIST;
+ }
+
+ @GET
+ @Produces({"application/xml", "text/plain", "application/json"})
+ @Path("shouldPickFirstXml")
+ public Person[] getXmlUnlessOtherwiseSpecified() {
+ return LIST;
+ }
+
+ @GET
+ @Produces("application/json;qs=0.75")
+ @Path("twoMethodsOneEndpoint")
+ public Person[] getJsonArray() {
+ return LIST;
+ }
+
+ @GET
+ @Produces("application/xml;qs=1")
+ @Path("twoMethodsOneEndpoint")
+ public Person[] getXml() {
+ return LIST;
+ }
+ }
+
+ @XmlRootElement
+ public static class Person {
+ private String name;
+ private int age;
+
+ public Person() {
+ }
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ @Override
+ public String toString() {
+ return name + "(" + age + ")";
+ }
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class);
+ }
+
+ /**
+ * {@link HttpUrlConnector} by default adds some media types
+ * to the Accept header if we don't specify them.
+ */
+ @Test
+ public void testWithoutDefinedRequestedMediaType() {
+ WebTarget target = target().path("/persons");
+ Response response = target.request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testWithoutDefinedRequestedMediaTypeAndTwoMethods() {
+ //We can not rely on method declaration ordering:
+ //From Class javadoc: "The elements in the returned array are not sorted and are not in any particular order."
+ //If there are same endpoints it is necessary to use quality parameter to ensure ordering.
+ Response response = target().path("/persons/twoMethodsOneEndpoint").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testWithoutDefinedRequestedMediaTypeOrQualityModifiersJson() {
+ Response response = target().path("/persons/shouldPickFirstJson").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testWithoutDefinedRequestedMediaTypeOrQualityModifiersXml() {
+ Response response = target().path("/persons/shouldPickFirstXml").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void test() {
+ WebTarget target = target().path("/persons");
+ Response response = target.request(MediaType.WILDCARD).get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testInverted() {
+ WebTarget target = target().path("/persons/inverted");
+ Response response = target.request(MediaType.WILDCARD).get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testInvertedWithJSONPreferredByClient() {
+ WebTarget target = target().path("/persons/inverted");
+ Response response = target.request("application/json;q=1.0", "application/xml;q=0.8").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testReordered() {
+ WebTarget target = target().path("/persons/reordered");
+ Response response = target.request(MediaType.WILDCARD).get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ /**
+ * Client and server prefers "unknown/hello" but there is no MBW on server to write such a type. Therefore
+ * this type is ignored and "application/xml" is chosen (because it is the second preferred type by the client).
+ */
+ @Test
+ public void testWithUnknownTypePreferredByClient() {
+ WebTarget target = target().path("/persons/reordered");
+ Response response = target.request("application/json;q=0.8", "application/xml;q=0.9",
+ "unknown/hello;qs=1.0").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesApplicationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesApplicationTest.java
new file mode 100644
index 0000000..494bff6
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesApplicationTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+import javax.inject.Inject;
+import javax.inject.Qualifier;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.inject.hk2.Hk2RequestScope;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.process.internal.RequestScope;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class CustomInjectablesApplicationTest extends JerseyTest {
+
+ public static class MyApplication extends Application {
+
+ public static Set<Class<?>> classes = new HashSet<Class<?>>() {{
+ add(Resource.class);
+ }};
+
+ @Inject
+ public MyApplication(InjectionManager injectionManager) {
+ System.out.println("Registering injectables...");
+ ClassBinding<MyInjectablePerRequest> injectClassRequest =
+ Bindings.serviceAsContract(MyInjectablePerRequest.class)
+ .in(RequestScoped.class);
+
+ ClassBinding<MyInjectableSingleton> injectClassSingleton =
+ Bindings.serviceAsContract(MyInjectableSingleton.class)
+ .in(Singleton.class);
+
+ InstanceBinding<MyInjectableSingleton> injectInstanceSingleton =
+ Bindings.serviceAsContract(new MyInjectableSingleton());
+
+ ClassBinding<MyInjectablePerRequest> injectQualifiedClassRequest =
+ Bindings.serviceAsContract(MyInjectablePerRequest.class)
+ .qualifiedBy(new MyQualifierImpl())
+ .in(RequestScoped.class);
+
+ injectionManager.register(Arrays.asList(
+ injectClassRequest, injectClassSingleton, injectInstanceSingleton, injectQualifiedClassRequest));
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return classes;
+ }
+ }
+
+ public static class MyInjectablePerRequest {
+ public int i = 0;
+ }
+
+ @Singleton
+ public static class MyInjectableSingleton {
+ public int i = 0;
+ }
+
+ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @Qualifier
+ public static @interface MyQualifier {
+
+ }
+
+ private static class MyQualifierImpl extends AnnotationLiteral<MyQualifier> implements MyQualifier {
+ }
+
+ @Path("/")
+ public static class Resource {
+ @Inject
+ MyInjectablePerRequest myInjectablePerRequest;
+
+ @Inject
+ MyInjectableSingleton myInjectableSingleton;
+
+ @Inject
+ @MyQualifier
+ MyInjectablePerRequest myInjectablePerRequest2;
+
+ @GET
+ @Path("/perrequest")
+ public String getAndIncPerRequest() {
+ return Integer.valueOf(++myInjectablePerRequest.i).toString();
+ }
+
+ @GET
+ @Path("/perrequestCustomQualifier")
+ public String getAndIncPerRequest2() {
+ return Integer.valueOf(++myInjectablePerRequest2.i).toString();
+ }
+
+ @GET
+ @Path("/singleton")
+ @Produces("text/plain")
+ public String getAndIncSingleton() {
+ System.out.println(myInjectableSingleton);
+ return Integer.valueOf(++myInjectableSingleton.i).toString();
+ }
+ }
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ // If strategy is not IMMEDIATE then test will fail even before @Before setup method invocation.
+ // It has no other reason then just run the tests in IMMEDIATE strategy.
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ return DeploymentContext.newInstance(MyApplication.class);
+ } else {
+ return DeploymentContext.newInstance(new ResourceConfig());
+ }
+ }
+
+ @Test
+ public void testPerRequest() throws Exception {
+ final javax.ws.rs.client.WebTarget perrequest = target().path("perrequest");
+
+ assertEquals("1", perrequest.request().get(String.class));
+ assertEquals("1", perrequest.request().get(String.class));
+ assertEquals("1", perrequest.request().get(String.class));
+ }
+
+ @Test
+ public void testSingleton() throws Exception {
+ final javax.ws.rs.client.WebTarget perrequest = target().path("singleton");
+
+ assertEquals("1", perrequest.request().get(String.class));
+ assertEquals("2", perrequest.request().get(String.class));
+ assertEquals("3", perrequest.request().get(String.class));
+ }
+
+ @Test
+ public void testCustomQualifier() throws Exception {
+ final javax.ws.rs.client.WebTarget perrequestCustomAnnotation = target().path("perrequestCustomQualifier");
+
+ assertEquals("1", perrequestCustomAnnotation.request().get(String.class));
+ assertEquals("1", perrequestCustomAnnotation.request().get(String.class));
+ assertEquals("1", perrequestCustomAnnotation.request().get(String.class));
+ }
+
+ @Test
+ public void plainHK2Test() throws Exception {
+ final InjectionManager injectionManager = Injections.createInjectionManager(
+ new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(Hk2RequestScope.class).to(RequestScope.class).in(Singleton.class);
+ bindAsContract(MyInjectablePerRequest.class).in(RequestScoped.class);
+ bindAsContract(MyInjectableSingleton.class).in(Singleton.class);
+ }
+ });
+ injectionManager.completeRegistration();
+
+ final RequestScope requestScope = injectionManager.getInstance(RequestScope.class);
+
+ final MyInjectableSingleton myInjectableSingleton = injectionManager.getInstance(MyInjectableSingleton.class);
+ assertEquals(myInjectableSingleton, injectionManager.getInstance(MyInjectableSingleton.class));
+
+ final MyInjectablePerRequest myInjectablePerRequest = requestScope.runInScope(new Callable<MyInjectablePerRequest>() {
+
+ @Override
+ public MyInjectablePerRequest call() throws Exception {
+ final MyInjectablePerRequest myInjectablePerRequest = injectionManager.getInstance(MyInjectablePerRequest.class);
+ assertEquals(myInjectablePerRequest, injectionManager.getInstance(MyInjectablePerRequest.class));
+ return myInjectablePerRequest;
+ }
+ });
+
+ requestScope.runInScope(new Runnable() {
+
+ @Override
+ public void run() {
+ assertNotSame(myInjectablePerRequest, injectionManager.getInstance(MyInjectablePerRequest.class));
+ }
+ });
+
+ }
+
+ @Test
+ public void plainHK2DynamicTest() throws Exception {
+ Binder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(Hk2RequestScope.class)
+ .to(RequestScope.class)
+ .in(Singleton.class);
+
+ bindAsContract(MyInjectablePerRequest.class)
+ .in(RequestScoped.class);
+
+ bindAsContract(MyInjectableSingleton.class)
+ .in(Singleton.class);
+ }
+ };
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ injectionManager.register(binder);
+ injectionManager.completeRegistration();
+
+ final RequestScope requestScope = injectionManager.getInstance(RequestScope.class);
+
+ final MyInjectableSingleton myInjectableSingleton = injectionManager.getInstance(MyInjectableSingleton.class);
+ assertEquals(myInjectableSingleton, injectionManager.getInstance(MyInjectableSingleton.class));
+
+ final MyInjectablePerRequest myInjectablePerRequest = requestScope.runInScope(new Callable<MyInjectablePerRequest>() {
+ @Override
+ public MyInjectablePerRequest call() throws Exception {
+ final MyInjectablePerRequest myInjectablePerRequest = injectionManager.getInstance(MyInjectablePerRequest.class);
+ assertEquals(myInjectablePerRequest, injectionManager.getInstance(MyInjectablePerRequest.class));
+ return myInjectablePerRequest;
+ }
+ });
+
+ requestScope.runInScope(new Runnable() {
+ @Override
+ public void run() {
+ assertNotSame(myInjectablePerRequest, injectionManager.getInstance(MyInjectablePerRequest.class));
+ }
+ });
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesResourceConfigTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesResourceConfigTest.java
new file mode 100644
index 0000000..836fb4d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomInjectablesResourceConfigTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+import javax.inject.Inject;
+import javax.inject.Qualifier;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class CustomInjectablesResourceConfigTest extends JerseyTest {
+
+ public static class MyHK2Binder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ // request scope binding
+ bindAsContract(MyInjectablePerRequest.class).in(RequestScoped.class);
+
+ // singleton binding
+ bindAsContract(MyInjectableSingleton.class).in(Singleton.class);
+
+ // singleton instance binding
+ bind(new MyInjectableSingleton()).to(MyInjectableSingleton.class);
+
+ // request scope binding with specified custom annotation
+ bindAsContract(MyInjectablePerRequest.class).qualifiedBy(new MyQualifierImpl()).in(RequestScoped.class);
+ }
+ }
+
+ public static class MyInjectablePerRequest {
+ public int i = 0;
+ }
+
+ @Singleton
+ public static class MyInjectableSingleton {
+ public int i = 0;
+ }
+
+ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @Qualifier
+ public static @interface MyQualifier {
+
+ }
+
+ private static class MyQualifierImpl extends AnnotationLiteral<MyQualifier> implements MyQualifier {
+ }
+
+ @Path("/")
+ public static class Resource {
+ @Inject
+ MyInjectablePerRequest myInjectablePerRequest;
+
+ @Inject
+ MyInjectableSingleton myInjectableSingleton;
+
+ @Inject
+ @MyQualifier
+ MyInjectablePerRequest myInjectablePerRequest2;
+
+ @GET
+ @Path("/perrequest")
+ public String getAndIncPerRequest() {
+ return Integer.valueOf(++myInjectablePerRequest.i).toString();
+ }
+
+ @GET
+ @Path("/perrequestCustomQualifier")
+ public String getAndIncPerRequest2() {
+ return Integer.valueOf(++myInjectablePerRequest2.i).toString();
+ }
+
+ @GET
+ @Path("/singleton")
+ @Produces("text/plain")
+ public String getAndIncSingleton() {
+ System.out.println(myInjectableSingleton);
+ return Integer.valueOf(++myInjectableSingleton.i).toString();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig rc = new ResourceConfig();
+ rc.registerClasses(Resource.class);
+ rc.register(new MyHK2Binder());
+
+ return rc;
+ }
+
+ @Test
+ public void testPerRequest() throws Exception {
+ final javax.ws.rs.client.WebTarget perRequest = target().path("perrequest");
+
+ assertEquals("1", perRequest.request().get(String.class));
+ assertEquals("1", perRequest.request().get(String.class));
+ assertEquals("1", perRequest.request().get(String.class));
+ }
+
+ @Test
+ public void testSingleton() throws Exception {
+ final javax.ws.rs.client.WebTarget perRequest = target().path("singleton");
+
+ assertEquals("1", perRequest.request().get(String.class));
+ assertEquals("2", perRequest.request().get(String.class));
+ assertEquals("3", perRequest.request().get(String.class));
+ }
+
+ @Test
+ public void testCustomAnnotation() throws Exception {
+ final javax.ws.rs.client.WebTarget perRequestCustomAnnotation = target().path("perrequestCustomQualifier");
+
+ assertEquals("1", perRequestCustomAnnotation.request().get(String.class));
+ assertEquals("1", perRequestCustomAnnotation.request().get(String.class));
+ assertEquals("1", perRequestCustomAnnotation.request().get(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomMultivaluedMapProviderTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomMultivaluedMapProviderTest.java
new file mode 100644
index 0000000..e9088df
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CustomMultivaluedMapProviderTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Tests that the Custom MultivaluedMap provider overrides the default
+ * EntityProvider
+ *
+ * @author Petr Bouda
+ */
+public class CustomMultivaluedMapProviderTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ TestResource.class,
+ CustomMultivaluedMapProvider.class);
+ }
+
+ @Provider
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public static class CustomMultivaluedMapProvider implements MessageBodyReader<MultivaluedMap<String, String>> {
+
+ @Override
+ public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return MultivaluedMap.class.isAssignableFrom(type);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public MultivaluedMap readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
+ MultivaluedMap map = new MultivaluedHashMap();
+ map.add(getClass().getSimpleName(), getClass().getSimpleName().replace("Provider", "Reader"));
+ return map;
+ }
+ }
+
+ @Path("resource")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public static class TestResource {
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public MultivaluedMap<String, String> map(MultivaluedMap<String, String> map) {
+ return map;
+ }
+
+ }
+
+ @Test
+ public void testNullFormParam() {
+ Response response = target("resource").request()
+ .post(Entity.entity("map", MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("CustomMultivaluedMapProvider=CustomMultivaluedMapReader", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedFormParamTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedFormParamTest.java
new file mode 100644
index 0000000..34d0379
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedFormParamTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Proper encoding of Form params
+ *
+ * @author Petr Bouda
+ */
+public class EncodedFormParamTest extends JerseyTest {
+
+ @Path("encoded")
+ public static class UrlEncodedResource {
+
+ @Encoded
+ @FormParam("name")
+ private String name;
+
+ @FormParam("name")
+ private String otherName;
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public String get(@FormParam("name") List<String> name) {
+ return name.toString() + " " + this.name;
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(UrlEncodedResource.class);
+ }
+
+ @Test
+ public void testEncodedParam() {
+ Response result = target().path("encoded").request()
+ .post(Entity.entity("name&name=George", MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ assertEquals("[null, George] null", result.readEntity(String.class));
+ }
+}
+
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedSlashInPathSegmentTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedSlashInPathSegmentTest.java
new file mode 100644
index 0000000..1d828f8
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EncodedSlashInPathSegmentTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for JERSEY-1167.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EncodedSlashInPathSegmentTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(EncodedSlashResource.class);
+ }
+
+ @Path("/test/{p}")
+ public static class EncodedSlashResource {
+
+ @GET
+ public String get(@PathParam("p") String p) {
+ return p;
+ }
+ }
+
+ @Test
+ public void testEncodedSlashInPathParam() throws Exception {
+
+ final Response response = target().path("test/one%2Ftwo").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("one/two", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EntityExpansionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EntityExpansionTest.java
new file mode 100644
index 0000000..fee7de4
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/EntityExpansionTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.glassfish.jersey.internal.util.SaxHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Tests properties configuring secure sax parsing.
+ *
+ * @author Miroslav Fuksa
+ */
+public class EntityExpansionTest extends JerseyTest {
+
+ private static final Logger LOG = Logger.getLogger(EntityExpansionTest.class.getName());
+ private static boolean isXdk = false;
+
+ @Override
+ protected Application configure() {
+ System.setProperty("entityExpansionLimit", "10");
+ System.setProperty("elementAttributeLimit", "1");
+
+ final ResourceConfig resourceConfig = new ResourceConfig(TestResource.class, BadRequestMapper.class);
+ return resourceConfig;
+ }
+
+ public static class BadRequestMapper implements ExceptionMapper<BadRequestException> {
+ @Override
+ public Response toResponse(BadRequestException exception) {
+ Throwable t = exception;
+ while (t != null && t.getClass() != SAXParseException.class) {
+ t = t.getCause();
+ }
+ if (t != null) {
+ return Response.ok().entity("PASSED:" + t.getMessage()).build();
+ }
+ return Response.status(500).build();
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @POST
+ public String post(TestBean bean) {
+ return bean.getInput();
+ }
+
+ }
+
+ @XmlRootElement()
+ @XmlAccessorType(value = XmlAccessType.FIELD)
+ public static class TestBean {
+ @XmlElement
+ private String input;
+
+ @XmlAttribute
+ private String str;
+
+ @XmlAttribute
+ private String str2;
+
+ @XmlAttribute
+ private String str3;
+
+
+ public String getStr2() {
+ return str2;
+ }
+
+ public void setStr2(String str2) {
+ this.str2 = str2;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+
+ public String getStr3() {
+ return str3;
+ }
+
+ public void setStr3(String str3) {
+ this.str3 = str3;
+ }
+
+ public String getInput() {
+ return input;
+ }
+
+ public void setInput(String input) {
+ this.input = input;
+ }
+ }
+
+ @BeforeClass
+ public static void setXdkFlag() {
+ // XDK SAXParser does not support this feature, so the test has to be skipped if XDK detected.
+ if (SaxHelper.isXdkParserFactory(SAXParserFactory.newInstance())) {
+ LOG.warning("XDK SAXParser detected, FEATURE_SECURE_PROCESSING is not supported. Tests will be skipped.");
+ isXdk = true;
+ }
+ Assume.assumeTrue(!isXdk);
+ }
+
+ @Test
+ public void testEntityExpansion() {
+ String str = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ + "\n<!DOCTYPE lolz [\n"
+ + " <!ENTITY lol \"lollollollollollollol[...]\">\n"
+ + " <!ENTITY lol2 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n"
+ + " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n"
+ + "]>\n"
+ + "<testBean><input>&lol3;</input></testBean>";
+
+ final Response response = target().path("resource").request().post(Entity.entity(str, MediaType.APPLICATION_XML));
+ Assert.assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ Assert.assertTrue(entity.startsWith("PASSED"));
+ }
+
+ @Test
+ public void testMaxAttributes() {
+ String str = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ + "<testBean str=\"aaa\" str2=\"bbb\" str3=\"ccc\"><input>test</input></testBean>";
+ final Response response = target().path("resource").request().post(Entity.entity(str, MediaType.APPLICATION_XML));
+ Assert.assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ Assert.assertTrue(entity.startsWith("PASSED"));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java
new file mode 100644
index 0000000..6d33ae7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.logging.Level;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Make sure exceptions, that are not mapped to responses get logged.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ExceptionLoggingTest extends JerseyTest {
+
+ private static class MyCheckedException extends Exception {}
+
+ private static class MyRuntimeException extends RuntimeException {}
+
+ @Path("/")
+ public static class ExceptionResource {
+
+ @Path("runtime")
+ public String runtimeException() {
+ throw new MyRuntimeException();
+ }
+
+ @Path("checked")
+ public String checkedException() throws MyCheckedException {
+ throw new MyCheckedException();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+
+ return new ResourceConfig(ExceptionResource.class, Writer.class, Resource.class);
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ final Response response = target().path("runtime").request().get();
+ assertEquals(500, response.getStatus());
+ assertEquals(getLastLoggedRecord().getThrown().getClass(), MyRuntimeException.class);
+ }
+
+ @Test
+ public void testChecked() throws Exception {
+ final Response response = target().path("checked").request().get();
+ assertEquals(500, response.getStatus());
+ assertEquals(getLastLoggedRecord().getThrown().getClass(), MyCheckedException.class);
+ }
+
+ @Provider
+ @Produces(MediaType.WILDCARD)
+ public static class Writer implements MessageBodyWriter<ExceptionLoggingTestPOJO> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == ExceptionLoggingTestPOJO.class;
+ }
+
+ @Override
+ public long getSize(ExceptionLoggingTestPOJO entityForReader, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return 0;
+ }
+
+ @Override
+ public void writeTo(ExceptionLoggingTestPOJO entityForReader, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ throw new RuntimeException("test");
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @Path("entity")
+ @GET
+ public ExceptionLoggingTestPOJO entity() {
+ return new ExceptionLoggingTestPOJO();
+ }
+ }
+
+ @Test
+ public void testReaderFails() throws Exception {
+ final Response response = target().path("resource/entity").request().get();
+ assertEquals(500, response.getStatus());
+
+ assertEquals(getLastLoggedRecord().getThrown().getMessage(), "test");
+ }
+
+ static class ExceptionLoggingTestPOJO {
+
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPriorityTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPriorityTest.java
new file mode 100644
index 0000000..cf25234
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPriorityTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ExceptionMapperPriorityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ExceptionMapperPriorityResource.class,
+ MyFirstExceptionMapper.class,
+ MySecondExceptionMapper.class,
+ MyThirdExceptionMapper.class);
+ }
+
+ @Test
+ public void priorityTest() {
+ String response = target().request().get(String.class);
+
+ assertThat(response, is(MySecondExceptionMapper.class.getName()));
+ }
+
+ @Path("/")
+ public static class ExceptionMapperPriorityResource {
+
+ @GET
+ public String get() throws MyException {
+ throw new MyException();
+ }
+ }
+
+ public static class MyException extends Exception {
+
+ }
+
+ @Provider
+ @Priority(300)
+ public static class MyFirstExceptionMapper implements ExceptionMapper<MyException> {
+
+ @Override
+ public Response toResponse(MyException exception) {
+ return Response.ok(MyFirstExceptionMapper.class.getName()).build();
+ }
+ }
+
+ @Provider
+ @Priority(100)
+ public static class MySecondExceptionMapper implements ExceptionMapper<MyException> {
+
+ @Override
+ public Response toResponse(MyException exception) {
+ return Response.ok(MySecondExceptionMapper.class.getName()).build();
+ }
+ }
+
+ @Provider
+ @Priority(200)
+ public static class MyThirdExceptionMapper implements ExceptionMapper<MyException> {
+
+ @Override
+ public Response toResponse(MyException exception) {
+ return Response.ok(MyThirdExceptionMapper.class.getName()).build();
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPropagationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPropagationTest.java
new file mode 100644
index 0000000..ef9daf7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperPropagationTest.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test exception mappers handling exceptions thrown from different part of code.
+ * <p/>
+ * There are more tests for exception mappers. This one focuses on testing that exceptions
+ * thrown from providers are correctly propagated to the exception mapper.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+@RunWith(ConcurrentRunner.class)
+public class ExceptionMapperPropagationTest extends JerseyTest {
+
+ public static final String EXCEPTION_TYPE = "exception-type";
+ public static final String MAPPED = "-mapped-";
+ public static final String MAPPED_WAE = "-wae-";
+ public static final String PROVIDER = "provider";
+
+ public static class TestRuntimeException extends RuntimeException {
+
+ public TestRuntimeException(String message) {
+ super(message);
+ }
+
+ }
+
+ public static class TestCheckedException extends Exception {
+
+ public TestCheckedException(String message) {
+ super(message);
+ }
+
+ }
+
+ public static class TestWebAppException extends WebApplicationException {
+
+ public TestWebAppException(String message, Response response) {
+ super(message, response);
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ UniversalThrowableMapper.class,
+ ExceptionResource.class,
+ TestResponseFilter.class,
+ TestRequestFilter.class,
+ WebAppMapper.class,
+ TestMBR.class,
+ TestMBW.class,
+ TestWriterInterceptor.class,
+ TestReaderInterceptor.class
+ );
+ }
+
+ public static class UniversalThrowableMapper implements ExceptionMapper<Throwable> {
+
+ @Override
+ public Response toResponse(Throwable exception) {
+ return Response.ok().entity(exception.getClass().getSimpleName() + MAPPED + exception.getMessage()).build();
+ }
+
+ }
+
+ public static class WebAppMapper implements ExceptionMapper<TestWebAppException> {
+
+ @Override
+ public Response toResponse(TestWebAppException exception) {
+ final Response response = exception.getResponse();
+ return Response.status(response.getStatus())
+ .entity(exception.getClass().getSimpleName() + MAPPED_WAE + exception.getMessage())
+ .build();
+ }
+ }
+
+ public static void throwException(String exceptionType, String provider, Class<?> currentClass) throws Throwable {
+
+ if (shouldThrow(exceptionType, provider, currentClass)) {
+ if (exceptionType.equals(TestCheckedException.class.getSimpleName())) {
+ throw new TestCheckedException(provider);
+ } else if (exceptionType.equals(TestRuntimeException.class.getSimpleName())) {
+ throw new TestRuntimeException(provider);
+ } else if (exceptionType.equals(TestWebAppException.class.getSimpleName())) {
+ throw new TestWebAppException(provider, Response.ok().build());
+ } else if (exceptionType.equals(ProcessingException.class.getSimpleName())) {
+ throw new ProcessingException(provider);
+ }
+ }
+ }
+
+ private static boolean shouldThrow(String exceptionType, String provider, Class<?> currentClass) {
+ return exceptionType != null && currentClass.getSimpleName().equals(provider);
+ }
+
+ @Path("exception")
+ public static class ExceptionResource {
+
+ @Path("general")
+ @POST
+ public Response post(@HeaderParam(EXCEPTION_TYPE) String exceptionType,
+ @HeaderParam(PROVIDER) String provider, String entity) throws Throwable {
+ throwException(exceptionType, provider, this.getClass());
+ return Response.ok().entity("exception/general#get called")
+ .header(EXCEPTION_TYPE, exceptionType)
+ .header(PROVIDER, provider).build();
+ }
+
+ @Path("sub")
+ public SubResourceLocator subResourceLocator(@HeaderParam(EXCEPTION_TYPE) String exceptionType,
+ @HeaderParam(PROVIDER) String provider) throws Throwable {
+ throwException(exceptionType, provider, this.getClass());
+ return new SubResourceLocator();
+ }
+
+ }
+
+ public static class SubResourceLocator {
+
+ @POST
+ public String post(@HeaderParam(EXCEPTION_TYPE) String exceptionType,
+ @HeaderParam(PROVIDER) String provider, String entity) throws Throwable {
+ throwException(exceptionType, provider, this.getClass());
+ return "sub-get";
+ }
+ }
+
+ public static class TestResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ final String exceptionType = responseContext.getHeaderString(EXCEPTION_TYPE);
+ final String provider = responseContext.getHeaderString(PROVIDER);
+
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+ }
+ }
+
+ public static class TestRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ final String exceptionType = requestContext.getHeaderString(EXCEPTION_TYPE);
+ final String provider = requestContext.getHeaderString(PROVIDER);
+
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+ }
+ }
+
+ @Consumes(MediaType.TEXT_PLAIN)
+ public static class TestMBR implements MessageBodyReader<String> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
+ WebApplicationException {
+ final String exceptionType = httpHeaders.getFirst(EXCEPTION_TYPE);
+ final String provider = httpHeaders.getFirst(PROVIDER);
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+
+ byte b;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while ((b = (byte) entityStream.read()) != -1) {
+ baos.write(b);
+ }
+ return new String(baos.toByteArray());
+ }
+ }
+
+ @Produces({"text/plain", "*/*"})
+ public static class TestMBW implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return 0;
+ }
+
+ @Override
+ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ final String exceptionType = (String) httpHeaders.getFirst(EXCEPTION_TYPE);
+ final String provider = (String) httpHeaders.getFirst(PROVIDER);
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+
+ entityStream.write(s.getBytes());
+ entityStream.flush();
+ }
+ }
+
+ @Consumes(MediaType.TEXT_PLAIN)
+ public static class TestReaderInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final String exceptionType = context.getHeaders().getFirst(EXCEPTION_TYPE);
+ final String provider = context.getHeaders().getFirst(PROVIDER);
+
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+ return context.proceed();
+ }
+ }
+
+ public static class TestWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final String exceptionType = (String) context.getHeaders().getFirst(EXCEPTION_TYPE);
+ final String provider = (String) context.getHeaders().getFirst(PROVIDER);
+
+ throwRuntimeExceptionAndIO(exceptionType, this.getClass(), provider);
+ context.proceed();
+ }
+ }
+
+ private static void throwRuntimeExceptionAndIO(String exceptionType, Class<?> providerClass, String provider)
+ throws IOException {
+ if (shouldThrow(exceptionType, provider, providerClass)) {
+ if (exceptionType.equals(TestRuntimeException.class.getSimpleName())) {
+ throw new TestRuntimeException(providerClass.getSimpleName());
+ } else if (exceptionType.equals(IOException.class.getSimpleName())) {
+ throw new IOException(providerClass.getSimpleName());
+ } else if (exceptionType.equals(TestWebAppException.class.getSimpleName())) {
+ throw new TestWebAppException(providerClass.getSimpleName(), Response.ok().build());
+ } else if (exceptionType.equals(ProcessingException.class.getSimpleName())) {
+ throw new ProcessingException(provider);
+ }
+ }
+ }
+
+ // Resource
+ @Test
+ public void testCheckedExceptionInResource() {
+ _test(TestCheckedException.class, ExceptionResource.class);
+ }
+
+ @Test
+ public void testRuntimeExceptionInResource() {
+ _test(TestRuntimeException.class, ExceptionResource.class);
+ }
+
+ @Test
+ public void testWebApplicationExceptionInResource() {
+ _testWae(ExceptionResource.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInResource() {
+ _test(ProcessingException.class, ExceptionResource.class);
+ }
+
+ // Sub resource
+ @Test
+ public void testCheckedExceptionInSubResourceLocatorMethod() {
+ _test(TestCheckedException.class, ExceptionResource.class, "exception/sub");
+ }
+
+ @Test
+ public void testRuntimeExceptionInSubResourceLocatorMethod() {
+ _test(TestRuntimeException.class, ExceptionResource.class, "exception/sub");
+ }
+
+ @Test
+ public void testWaeInSubResourceLocatorMethod() {
+ _testWae(ExceptionResource.class, "exception/sub");
+ }
+
+ @Test
+ public void testProcessingExceptionInSubResourceLocatorMethod() {
+ _test(ProcessingException.class, ExceptionResource.class, "exception/sub");
+ }
+
+ @Test
+ public void testCheckedExceptionInSubResource() {
+ _test(TestCheckedException.class, SubResourceLocator.class, "exception/sub");
+ }
+
+ @Test
+ public void testRuntimeExceptionInSubResource() {
+ _test(TestRuntimeException.class, SubResourceLocator.class, "exception/sub");
+ }
+
+ @Test
+ public void testWaeInSubResource() {
+ _testWae(SubResourceLocator.class, "exception/sub");
+ }
+
+ @Test
+ public void testProcessingExceptionInSubResource() {
+ _test(ProcessingException.class, SubResourceLocator.class, "exception/sub");
+ }
+
+ // response filters
+ @Test
+ public void testRuntimeExceptionInResponseFilter() {
+ _test(TestRuntimeException.class, TestResponseFilter.class);
+ }
+
+ @Test
+ public void testIOExceptionInResponseFilter() {
+ _test(IOException.class, TestResponseFilter.class);
+ }
+
+ @Test
+ public void testWaeInResponseFilter() {
+ _testWae(TestResponseFilter.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInResponseFilter() {
+ _test(ProcessingException.class, TestResponseFilter.class);
+ }
+
+ // response filters
+ @Test
+ public void testRuntimeExceptionInRequestFilter() {
+ _test(TestRuntimeException.class, TestRequestFilter.class);
+ }
+
+ @Test
+ public void testIOExceptionInRequestFilter() {
+ _test(IOException.class, TestRequestFilter.class);
+ }
+
+ @Test
+ public void testWaeInRequestFilter() {
+ _testWae(TestRequestFilter.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInRequestFilter() {
+ _test(ProcessingException.class, TestRequestFilter.class);
+ }
+
+ // MBR/W
+ @Test
+ public void testRuntimeExceptionInMBW() {
+ _test(TestRuntimeException.class, TestMBW.class);
+ }
+
+ @Test
+ public void testIOExceptionInMBW() {
+ _test(IOException.class, TestMBW.class);
+ }
+
+ @Test
+ public void testWaeInMBW() {
+ _testWae(TestMBW.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInMBW() {
+ _test(ProcessingException.class, TestMBW.class);
+ }
+
+ @Test
+ public void testRuntimeExceptionInMBR() {
+ _test(TestRuntimeException.class, TestMBR.class);
+ }
+
+ @Test
+ public void testIOExceptionInMBR() {
+ _test(IOException.class, TestMBR.class);
+ }
+
+ @Test
+ public void testWaeInMBR() {
+ _testWae(TestMBR.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInMBR() {
+ _test(ProcessingException.class, TestMBR.class);
+ }
+
+ // interceptors
+ @Test
+ public void testRuntimeExceptionInReaderInterceptor() {
+ _test(TestRuntimeException.class, TestReaderInterceptor.class);
+ }
+
+ @Test
+ public void testIOExceptionInReaderInterceptor() {
+ _test(IOException.class, TestReaderInterceptor.class);
+ }
+
+ @Test
+ public void testWaeInReaderInterceptor() {
+ _testWae(TestReaderInterceptor.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInReaderInterceptor() {
+ _test(ProcessingException.class, TestReaderInterceptor.class);
+ }
+
+ @Test
+ public void testRuntimeExceptionInWriterInterceptor() {
+ _test(TestRuntimeException.class, TestWriterInterceptor.class);
+ }
+
+ @Test
+ public void testIOExceptionInWriterInterceptor() {
+ _test(IOException.class, TestWriterInterceptor.class);
+ }
+
+ @Test
+ public void testWaeInWriterInterceptor() {
+ _testWae(TestWriterInterceptor.class);
+ }
+
+ @Test
+ public void testProcessingExceptionInWriterInterceptor() {
+ _test(ProcessingException.class, TestWriterInterceptor.class);
+ }
+
+ private void _test(Class<?> exceptionClass, Class<?> providerClass, String path) {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ final Response response = target(path).request()
+ .header(EXCEPTION_TYPE, exceptionClass.getSimpleName()).header(PROVIDER, providerClass.getSimpleName())
+ .accept(MediaType.TEXT_PLAIN_TYPE)
+ .post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(exceptionClass.getSimpleName() + MAPPED + providerClass.getSimpleName(), response.readEntity(String.class));
+ }
+
+ private void _testWae(Class<?> providerClass) {
+ final String path = "exception/general";
+ _testWae(providerClass, path);
+
+ }
+
+ private void _testWae(Class<?> providerClass, String path) {
+ final Class<?> exceptionClass = TestWebAppException.class;
+
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ final Response response = target(path).request()
+ .header(EXCEPTION_TYPE, exceptionClass.getSimpleName()).header(PROVIDER, providerClass.getSimpleName())
+ .accept(MediaType.TEXT_PLAIN_TYPE)
+ .post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(exceptionClass.getSimpleName() + MAPPED_WAE + providerClass.getSimpleName(),
+ response.readEntity(String.class));
+ }
+
+ private void _test(Class<?> exceptionClass, Class<?> providerClass) {
+ final String path = "exception/general";
+ _test(exceptionClass, providerClass, path);
+ }
+
+ // sub resource locator
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java
new file mode 100644
index 0000000..6ebbac5
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests throwing exceptions in {@link MessageBodyReader} and {@link MessageBodyWriter}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ExceptionMapperTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ Resource.class,
+ MyMessageBodyWritter.class,
+ MyMessageBodyReader.class,
+ ClientErrorExceptionMapper.class,
+ MyExceptionMapper.class,
+ ThrowableMapper.class,
+ MyExceptionMapperCauseAnotherException.class,
+ // JERSEY-1515
+ TestResource.class,
+ VisibilityExceptionMapper.class,
+ // JERSEY-1525
+ ExceptionTestResource.class,
+ ExceptionThrowingFilter.class,
+ IOExceptionMapper.class,
+ IOExceptionMessageReader.class,
+ IOExceptionResource.class,
+ MessageBodyProviderNotFoundResource.class,
+ ProviderNotFoundExceptionMapper.class,
+ // JERSEY-1887
+ Jersey1887Resource.class,
+ Jersey1887ExceptionMapperImpl.class,
+ // JERSEY-2382
+ Jersey2382Resource.class,
+ Jersey2382ExceptionMapper.class,
+ Jersey2382Provider.class
+ );
+ }
+
+ @Test
+ public void testReaderThrowsException() {
+ Response res = target().path("test").request("test/test").header("reader-exception", "throw")
+ .post(Entity.entity("post", "test/test"));
+ assertEquals(200, res.getStatus());
+ final String entity = res.readEntity(String.class);
+ assertEquals("reader-exception-mapper", entity);
+ }
+
+ @Test
+ public void testWriterThrowsExceptionBeforeFirstBytesAreWritten() {
+ Response res = target().path("test/before").request("test/test").get();
+ assertEquals(200, res.getStatus());
+ assertEquals("exception-before-first-bytes-exception-mapper", res.readEntity(String.class));
+ }
+
+ @Test
+ public void testWriterThrowsExceptionAfterFirstBytesAreWritten() throws IOException {
+ Response res = target().path("test/after").request("test/test").get();
+ assertEquals(200, res.getStatus());
+ final InputStream inputStream = res.readEntity(InputStream.class);
+ byte b;
+ inputStream.read();
+ MyMessageBodyWritter.firstBytesReceived = true;
+ while ((b = (byte) inputStream.read()) >= 0) {
+ assertEquals('a', b);
+ }
+ }
+
+ @Test
+ public void testPreventMultipleExceptionMapping() {
+ Response res = target().path("test/exception").request("test/test").get();
+ // firstly exception is thrown in the resource method and is correctly mapped. Then it is again thrown in MBWriter but
+ // exception can be mapped only once, so second exception in MBWriter cause 500 response code.
+ assertEquals(500, res.getStatus());
+ }
+
+ @Path("test")
+ public static class Resource {
+
+ @GET
+ @Path("before")
+ @Produces("test/test")
+ public Response exceptionBeforeFirstBytesAreWritten() {
+ return Response.status(200).header("writer-exception", "before-first-byte").entity("ok").build();
+ }
+
+ @GET
+ @Path("after")
+ @Produces("test/test")
+ public Response exceptionAfterFirstBytesAreWritten() {
+ return Response.status(200).header("writer-exception", "after-first-byte").entity("aaaaa").build();
+ }
+
+ @POST
+ @Produces("test/test")
+ public String post(String str) {
+ return "post";
+ }
+
+ @GET
+ @Path("exception")
+ @Produces("test/test")
+ public Response throwsException() {
+ throw new MyAnotherException("resource");
+ }
+
+ @Path("throwable")
+ @GET
+ public String throwsThrowable() throws Throwable {
+ throw new Throwable("throwable",
+ new RuntimeException("runtime-exception",
+ new ClientErrorException("client-error", 499)));
+ }
+ }
+
+ public static class ClientErrorExceptionMapper implements ExceptionMapper<ClientErrorException> {
+
+ @Override
+ public Response toResponse(ClientErrorException exception) {
+ return Response.status(Response.Status.OK).entity("mapped-client-error-"
+ + exception.getResponse().getStatus() + "-" + exception.getMessage()).build();
+ }
+ }
+
+ public static class MyExceptionMapper implements ExceptionMapper<MyException> {
+
+ @Override
+ public Response toResponse(MyException exception) {
+ return Response.ok().entity(exception.getMessage() + "-exception-mapper").build();
+ }
+ }
+
+ public static class ThrowableMapper implements ExceptionMapper<Throwable> {
+
+ @Override
+ public Response toResponse(Throwable throwable) {
+ throwable.printStackTrace();
+ return Response.status(Response.Status.OK).entity("mapped-throwable-" + throwable.getMessage()).build();
+ }
+
+ }
+
+ public static class MyExceptionMapperCauseAnotherException implements ExceptionMapper<MyAnotherException> {
+
+ @Override
+ public Response toResponse(MyAnotherException exception) {
+ // the header causes exception to be thrown again in MyMessageBodyWriter
+ return Response.ok().header("writer-exception", "before-first-byte").entity(exception.getMessage()
+ + "-another-exception-mapper").build();
+ }
+ }
+
+ @Produces("test/test")
+ public static class MyMessageBodyWritter implements MessageBodyWriter<String> {
+
+ public static volatile boolean firstBytesReceived;
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return s.length();
+ }
+
+ @Override
+ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ firstBytesReceived = false;
+
+ final List<Object> header = httpHeaders.get("writer-exception");
+
+ if (header != null && header.size() > 0) {
+ if (header.get(0).equals("before-first-byte")) {
+ throw new MyException("exception-before-first-bytes");
+ } else if (header.get(0).equals("after-first-byte")) {
+ int i = 0;
+ while (!firstBytesReceived && i++ < 500000) {
+ entityStream.write('a');
+ entityStream.flush();
+ }
+ throw new MyException("exception-after-first-bytes");
+ }
+ } else {
+ OutputStreamWriter osw = new OutputStreamWriter(entityStream);
+ osw.write(s);
+ osw.flush();
+ }
+ }
+ }
+
+ @Consumes("test/test")
+ public static class MyMessageBodyReader implements MessageBodyReader<String> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
+ WebApplicationException {
+ final List<String> header = httpHeaders.get("reader-exception");
+ if (header != null && header.size() > 0 && header.get(0).equals("throw")) {
+ throw new MyException("reader");
+ }
+ return "aaa";
+ }
+ }
+
+ public static class MyException extends RuntimeException {
+
+ public MyException() {
+ }
+
+ public MyException(Throwable cause) {
+ super(cause);
+ }
+
+ public MyException(String message) {
+ super(message);
+ }
+
+ public MyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ public static class MyAnotherException extends RuntimeException {
+
+ public MyAnotherException() {
+ }
+
+ public MyAnotherException(Throwable cause) {
+ super(cause);
+ }
+
+ public MyAnotherException(String message) {
+ super(message);
+ }
+
+ public MyAnotherException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ /**
+ * BEGIN: JERSEY-1515 reproducer code
+ */
+ public static class VisibilityException extends WebApplicationException {
+
+ private static final long serialVersionUID = -1159407312691372429L;
+
+ }
+
+ public static class VisibilityExceptionMapper implements ExceptionMapper<VisibilityException> {
+
+ private HttpHeaders headers;
+ private UriInfo info;
+ private Application application;
+ private Request request;
+ private Providers provider;
+
+ protected VisibilityExceptionMapper(@Context HttpHeaders headers,
+ @Context UriInfo info, @Context Application application,
+ @Context Request request, @Context Providers provider) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ this.request = request;
+ this.provider = provider;
+ }
+
+ public VisibilityExceptionMapper(@Context HttpHeaders headers,
+ @Context UriInfo info, @Context Application application,
+ @Context Request request) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ this.request = request;
+ }
+
+ public VisibilityExceptionMapper(@Context HttpHeaders headers,
+ @Context UriInfo info, @Context Application application) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ }
+
+ public VisibilityExceptionMapper(@Context HttpHeaders headers,
+ @Context UriInfo info) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ }
+
+ public VisibilityExceptionMapper(@Context HttpHeaders headers) {
+ super();
+ this.headers = headers;
+ }
+
+ @Override
+ public Response toResponse(VisibilityException exception) {
+ return Response.ok("visible").build();
+ }
+ }
+
+ @Path("test/visible")
+ public static class TestResource {
+
+ @GET
+ public String throwVisibleException() {
+ throw new VisibilityException();
+ }
+ }
+
+ @Test
+ public void testJersey1515() {
+ Response res = target().path("test/visible").request().get();
+ assertEquals(200, res.getStatus());
+ assertEquals("visible", res.readEntity(String.class));
+ }
+ /**
+ * END: JERSEY-1515 reproducer code
+ */
+
+ /**
+ * BEGIN: JERSEY-1525 reproducer code.
+ */
+ @Path("test/responseFilter")
+ public static class ExceptionTestResource {
+
+ @GET
+ @ThrowsNPE
+ public String getData() {
+ return "method";
+ }
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface ThrowsNPE {
+ }
+
+ @ThrowsNPE
+ public static class ExceptionThrowingFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext,
+ ContainerResponseContext responseContext) throws IOException {
+ // The if clause prevents throwing exception on a mapped response.
+ // Not doing so would result in a second exception being thrown
+ // which would not be mapped again; instead, it would be propagated
+ // to the hosting container directly.
+ if (!"mapped-throwable-response-filter-exception".equals(responseContext.getEntity())) {
+ throw new NullPointerException("response-filter-exception");
+ }
+ }
+ }
+
+ @Test
+ public void testJersey1525() {
+ Response res = target().path("test/responseFilter").request().get();
+ assertEquals(200, res.getStatus());
+ assertEquals("mapped-throwable-response-filter-exception", res.readEntity(String.class));
+ }
+
+ /**
+ * END: JERSEY-1525 reproducer code
+ */
+
+ @Provider
+ public static class IOExceptionMessageReader implements MessageBodyReader<IOBean>, MessageBodyWriter<IOBean> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == IOBean.class;
+ }
+
+ @Override
+ public IOBean readFrom(Class<IOBean> type,
+ Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ throw new IOException("io-exception");
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == IOBean.class;
+ }
+
+ @Override
+ public long getSize(IOBean ioBean, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return 0;
+ }
+
+ @Override
+ public void writeTo(IOBean ioBean, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ entityStream.write(ioBean.value.getBytes());
+
+ }
+ }
+
+ public static class IOBean {
+
+ private final String value;
+
+ public IOBean(String value) {
+ this.value = value;
+ }
+ }
+
+ public static class IOExceptionMapper implements ExceptionMapper<IOException> {
+
+ @Override
+ public Response toResponse(IOException exception) {
+ return Response.ok("passed").build();
+ }
+ }
+
+ @Path("io")
+ public static class IOExceptionResource {
+
+ @POST
+ public String post(IOBean iobean) {
+ return iobean.value;
+ }
+ }
+
+ @Test
+ public void testIOException() {
+ final Response response = target().register(IOExceptionMessageReader.class)
+ .path("io").request().post(Entity.entity(new IOBean("io-bean"), MediaType.TEXT_PLAIN));
+ assertEquals(200, response.getStatus());
+ assertEquals("passed", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testThrowableFromResourceMethod() {
+ Response res = target().path("test/throwable").request().get();
+ assertEquals(200, res.getStatus());
+ assertEquals("mapped-throwable-throwable", res.readEntity(String.class));
+ }
+
+ @Path("not-found")
+ public static class MessageBodyProviderNotFoundResource {
+
+ @GET
+ @Produces("aa/bbb")
+ public UnknownType get() {
+ return new UnknownType();
+ }
+ }
+
+ public static class UnknownType {
+
+ }
+
+ public static class ProviderNotFoundExceptionMapper implements ExceptionMapper<InternalServerErrorException> {
+
+ @Override
+ public Response toResponse(InternalServerErrorException exception) {
+ if (exception.getCause() instanceof MessageBodyProviderNotFoundException) {
+ return Response.ok("mapped-by-ProviderNotFoundExceptionMapper").build();
+ }
+ return Response.serverError().entity("Unexpected root cause of InternalServerError").build();
+ }
+ }
+
+ /**
+ * Tests that {@link MessageBodyProviderNotFoundException} wrapped into {@link javax.ws.rs.InternalServerErrorException}
+ * is correctly mapped using an {@link ExceptionMapper}.
+ */
+ @Test
+ public void testNotFoundResource() {
+ final Response response = target().path("not-found").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("mapped-by-ProviderNotFoundExceptionMapper", response.readEntity(String.class));
+ }
+
+ public static class Jersey1887Exception extends RuntimeException {
+ }
+
+ @Provider
+ public static interface Jersey1887ExceptionMapper extends ExceptionMapper<Jersey1887Exception> {
+ }
+
+ public static class Jersey1887ExceptionMapperImpl implements Jersey1887ExceptionMapper {
+
+ @Override
+ public Response toResponse(final Jersey1887Exception exception) {
+ return Response.ok("found").build();
+ }
+ }
+
+ @Path("jersey1887")
+ public static class Jersey1887Resource {
+
+ @GET
+ public Response get() {
+ throw new Jersey1887Exception();
+ }
+ }
+
+ /**
+ * Test that we're able to use correct exception mapper even when the mapper hierarchy has complex inheritance.
+ */
+ @Test
+ public void testJersey1887() throws Exception {
+ final Response response = target().path("jersey1887").request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("found"));
+ }
+
+ public static class Jersey2382Exception extends RuntimeException {
+ }
+
+ public static class Jersey2382Entity {
+ }
+
+ @Provider
+ public static class Jersey2382Provider implements MessageBodyWriter<Jersey2382Entity> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final Jersey2382Entity jersey2382Entity, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Jersey2382Entity jersey2382Entity,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ if (Jersey2382Entity.class != type) {
+ entityStream.write("wrong-type".getBytes());
+ } else if (Jersey2382Entity.class != genericType) {
+ entityStream.write("wrong-generic-type".getBytes());
+ } else {
+ entityStream.write("ok".getBytes());
+ }
+ }
+ }
+
+ @Provider
+ public static class Jersey2382ExceptionMapper implements ExceptionMapper<Jersey2382Exception> {
+
+ @Override
+ public Response toResponse(final Jersey2382Exception exception) {
+ return Response.ok(new Jersey2382Entity()).build();
+ }
+ }
+
+ @Path("jersey2382")
+ public static class Jersey2382Resource {
+
+ @GET
+ public List<List<Integer>> get() {
+ throw new Jersey2382Exception();
+ }
+ }
+
+ /**
+ * Test that we're able to use correct exception mapper even when the mapper hierarchy has complex inheritance.
+ */
+ @Test
+ public void testJersey2382() throws Exception {
+ final Response response = target().path("jersey2382").request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("ok"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java
new file mode 100644
index 0000000..350b8c4
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.LocalizationMessages;
+import org.glassfish.jersey.spi.ExtendedExceptionMapper;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Miroslav Fuksa
+ *
+ */
+public class ExtendedExceptionMapperTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+
+ return new ResourceConfig(
+ TestResource.class,
+ ExceptionMapperA.class,
+ ExceptionMapperB.class,
+ ExceptionMapperC.class,
+ ExceptionMapperD.class,
+ ExceptionMapperE.class,
+ ExceptionMapperX.class
+ );
+ }
+
+ public static class ExceptionA extends RuntimeException {
+ public ExceptionA(String message) {
+ super(message);
+ }
+ }
+
+ public static class ExceptionB extends ExceptionA {
+ public ExceptionB(String message) {
+ super(message);
+ }
+ }
+
+ public static class ExceptionC extends ExceptionB {
+ public ExceptionC(String message) {
+ super(message);
+ }
+ }
+
+ public static class ExceptionD extends ExceptionC {
+ public ExceptionD(String message) {
+ super(message);
+ }
+ }
+
+ public static class ExceptionE extends ExceptionD {
+ public ExceptionE(String message) {
+ super(message);
+ }
+ }
+
+ public static class ExceptionX extends RuntimeException {
+ public ExceptionX(String message) {
+ super(message);
+ }
+ }
+
+
+ public static class ExceptionMapperA implements ExtendedExceptionMapper<ExceptionA> {
+
+ @Override
+ public boolean isMappable(ExceptionA exception) {
+ return exception.getMessage().substring(2).contains("A");
+ }
+
+ @Override
+ public Response toResponse(ExceptionA exception) {
+ return Response.ok("A").build();
+ }
+ }
+
+ public static class ExceptionMapperB implements ExtendedExceptionMapper<ExceptionB> {
+
+ @Override
+ public boolean isMappable(ExceptionB exception) {
+ return exception.getMessage().substring(2).contains("B");
+ }
+
+ @Override
+ public Response toResponse(ExceptionB exception) {
+ return Response.ok("B").build();
+ }
+ }
+
+ public static class ExceptionMapperC implements ExceptionMapper<ExceptionC> {
+
+ @Override
+ public Response toResponse(ExceptionC exception) {
+ return Response.ok("C").build();
+ }
+ }
+
+ public static class ExceptionMapperD implements ExtendedExceptionMapper<ExceptionD> {
+
+ @Override
+ public boolean isMappable(ExceptionD exception) {
+ return exception.getMessage().substring(2).contains("D");
+ }
+
+ @Override
+ public Response toResponse(ExceptionD exception) {
+ return Response.ok("D").build();
+ }
+ }
+
+ public static class ExceptionMapperE implements ExtendedExceptionMapper<ExceptionE> {
+
+ @Override
+ public boolean isMappable(ExceptionE exception) {
+ return exception.getMessage().substring(2).contains("E");
+ }
+
+ @Override
+ public Response toResponse(ExceptionE exception) {
+ return Response.ok("E").build();
+ }
+ }
+
+ public static class ExceptionMapperX implements ExtendedExceptionMapper<ExceptionX> {
+
+ @Override
+ public boolean isMappable(ExceptionX exception) {
+ return exception.getMessage().substring(2).contains("X");
+ }
+
+ @Override
+ public Response toResponse(ExceptionX exception) {
+ return Response.ok("X").build();
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+ @POST
+ public String post(String e) {
+ if (e.charAt(0) == 'A') {
+ throw new ExceptionA(String.valueOf(e));
+ } else if (e.charAt(0) == 'B') {
+ throw new ExceptionB(String.valueOf(e));
+ } else if (e.charAt(0) == 'C') {
+ throw new ExceptionC(String.valueOf(e));
+ } else if (e.charAt(0) == 'D') {
+ throw new ExceptionD(String.valueOf(e));
+ } else if (e.charAt(0) == 'E') {
+ throw new ExceptionE(String.valueOf(e));
+ } else if (e.charAt(0) == 'X') {
+ throw new ExceptionX(String.valueOf(e));
+ }
+ return "get";
+ }
+ }
+
+ @Test
+ public void test() {
+ // Format of first param: [exception thrown]-[exception mappers which will return true in isMappable]
+ _test("A-A", "A");
+ _test("A-AB", "A");
+ _test("A-ABC", "A");
+ _test("A-ABCD", "A");
+ _test("A-ABCDE", "A");
+ _test("A-ABCDEX", "A");
+ _test("A-C", null);
+ _test("A-D", null);
+ _test("A-E", null);
+ _test("A-D", null);
+ _test("A-BCDEX", null);
+ _test("A-00000", null);
+ _test("A-X", null);
+
+
+ _test("B-A", "A");
+ _test("B-B", "B");
+ _test("B-AB", "B");
+ _test("B-ABC", "B");
+ _test("B-ABCD", "B");
+ _test("B-ABCDE", "B");
+ _test("B-ABCDEX", "B");
+ _test("B-C", null);
+ _test("B-D", null);
+ _test("B-E", null);
+ _test("B-CDEX", null);
+ _test("B-X", null);
+ _test("B-000", null);
+
+ // C is not an ExtendedExceptionMapper but just ExceptionMapper (always mappable)
+ _test("C-C", "C");
+ _test("C-A", "C");
+ _test("C-AB", "C");
+ _test("C-ABC", "C");
+ _test("C-AEX", "C");
+ _test("C-00000", "C");
+ _test("C-ABCDEX", "C");
+ _test("C-E", "C");
+ _test("C-DE", "C");
+ _test("C-D", "C");
+ _test("C-X", "C");
+
+ _test("D-000", "C");
+ _test("D-A", "C");
+ _test("D-B", "C");
+ _test("D-C", "C");
+ _test("D-D", "D");
+ _test("D-E", "C");
+ _test("D-ABC", "C");
+ _test("D-ABCEX", "C");
+ _test("D-ABCDEX", "D");
+ _test("D-DE", "D");
+ _test("D-ABEX", "C");
+ _test("D-AEX", "C");
+ _test("D-X", "C");
+
+ _test("E-A", "C");
+ _test("E-B", "C");
+ _test("E-C", "C");
+ _test("E-D", "D");
+ _test("E-E", "E");
+ _test("E-ABC", "C");
+ _test("E-ABCD", "D");
+ _test("E-ABCDE", "E");
+ _test("E-ABCDEX", "E");
+ _test("E-DE", "E");
+ _test("E-X", "C");
+ _test("E-000000", "C");
+
+ _test("X-A", null);
+ _test("X-ABCDE", null);
+ _test("X-ABCDEX", "X");
+ _test("X-X", "X");
+
+ // Check logs. (??)
+ for (final LogRecord logRecord : getLoggedRecords()) {
+
+ // TODO: this test is fragile.
+ if (logRecord.getLoggerName().contains("ClientExecutorProvidersConfigurator")) {
+ continue;
+ }
+
+ for (final String message : new String[]{
+ LocalizationMessages.ERROR_EXCEPTION_MAPPING_ORIGINAL_EXCEPTION(),
+ LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER()}) {
+
+ if (logRecord.getMessage().contains(message) && logRecord.getLevel().intValue() > Level.FINE.intValue()) {
+ fail("Log message should be logged at lower (FINE) level: " + message);
+ }
+ }
+ }
+ }
+
+ private void _test(String input, String expectedMapper) {
+ final Response response = target("resource").request().post(Entity.entity(input, MediaType.TEXT_PLAIN_TYPE));
+ if (expectedMapper == null) {
+ Assert.assertEquals(500, response.getStatus());
+ } else {
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(expectedMapper, response.readEntity(String.class));
+ }
+ }
+
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedUriInfoTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedUriInfoTest.java
new file mode 100644
index 0000000..b88f94e
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedUriInfoTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Objects;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.server.ExtendedUriInfo;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * {@link ExtendedUriInfo} e2e tests - testing e.g. getting matched resources, mapped throwable, etc.
+ *
+ * @author Michal Gajdos
+ */
+public class ExtendedUriInfoTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ThrowableResource.class, MappedThrowableResponseFilter.class, MappedExceptionMapper.class);
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface MappedThrowable {}
+
+ @Path("mapped-throwable-test")
+ @MappedThrowable
+ public static class ThrowableResource {
+
+ @GET
+ @Path("unmapped")
+ public Response unmapped() {
+ throw new RuntimeException();
+ }
+
+ @GET
+ @Path("mapped")
+ public Response mapped() {
+ throw new MappedException();
+ }
+
+ @GET
+ @Path("webapp")
+ public Response webapp() {
+ throw new InternalServerErrorException();
+ }
+
+ @GET
+ @Path("regular")
+ public Response regular() {
+ return Response.ok().build();
+ }
+ }
+
+ public static class MappedException extends RuntimeException {
+ }
+
+ public static class MappedExceptionMapper implements ExceptionMapper<MappedException> {
+
+ @Override
+ public Response toResponse(final MappedException exception) {
+ return Response.ok().build();
+ }
+ }
+
+ @MappedThrowable
+ public static class MappedThrowableResponseFilter implements ContainerResponseFilter {
+
+ @Inject
+ private ExtendedUriInfo uriInfo;
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
+ throws IOException {
+ responseContext.setEntity(Objects.toString(uriInfo.getMappedThrowable()));
+ }
+ }
+
+ @Test
+ public void testUnmappedThrowableValue() throws Exception {
+ assertThat("Internal Server Error expected - response filter not invoked",
+ target("mapped-throwable-test/unmapped").request().get().getStatus(),
+ is(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()));
+ }
+
+ @Test
+ public void testMappedThrowableValue() throws Exception {
+ assertThat("MappedException expected in ExtendedUriInfo#getMappedThrowable",
+ target("mapped-throwable-test/mapped").request().get().readEntity(String.class),
+ is("org.glassfish.jersey.tests.e2e.server.ExtendedUriInfoTest$MappedException"));
+ }
+
+ @Test
+ public void testWebAppThrowableValue() throws Exception {
+ assertThat("InternalServerErrorException expected in ExtendedUriInfo#getMappedThrowable",
+ target("mapped-throwable-test/webapp").request().get().readEntity(String.class),
+ containsString("javax.ws.rs.InternalServerErrorException"));
+ }
+
+ @Test
+ public void testRegularResourceValue() throws Exception {
+ assertThat("null expected in ExtendedUriInfo#getMappedThrowable",
+ target("mapped-throwable-test/regular").request().get().readEntity(String.class),
+ is("null"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/FormParamMultivaluedInjectionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/FormParamMultivaluedInjectionTest.java
new file mode 100644
index 0000000..8270802
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/FormParamMultivaluedInjectionTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the MultivaluedMap injection does not close the request buffer and allows
+ * to proceed other FormParam injections.
+ *
+ * @author Petr Bouda
+ */
+public class FormParamMultivaluedInjectionTest extends JerseyTest {
+
+ public static final String PREDEFINED_RESPONSE = "Hello George Javatar";
+
+ @Path("form")
+ public static class FormResource {
+
+ @POST
+ @Path("simple")
+ public Response simple(MultivaluedMap<String, String> formParams,
+ @FormParam("firstname") String firstname,
+ @FormParam("lastname") String lastname) {
+ assertEquals(2, formParams.size());
+ assertEquals("George", formParams.get("firstname").get(0));
+ assertEquals("Javatar", formParams.get("lastname").get(0));
+ return Response.status(Response.Status.OK).entity("Hello " + firstname + " " + lastname).build();
+ }
+
+ @POST
+ @Path("nullable")
+ public Response nullable(MultivaluedMap<String, String> formParams,
+ @FormParam("firstname") String firstname,
+ @FormParam("lastname") String lastname) {
+ assertEquals(2, formParams.size());
+ assertEquals(2, formParams.get("firstname").size());
+ assertEquals("George", formParams.get("firstname").get(0));
+ assertEquals("Javatar", formParams.get("lastname").get(0));
+ return Response.status(Response.Status.OK).entity("Hello " + firstname + " " + lastname).build();
+ }
+
+ @POST
+ @Path("mixed")
+ public Response mixed(@FormParam("firstname") String firstname,
+ MultivaluedMap<String, String> formParams,
+ @FormParam("lastname") String lastname) {
+ assertEquals(2, formParams.size());
+ assertEquals(2, formParams.get("firstname").size());
+ assertEquals("George", formParams.get("firstname").get(0));
+ assertEquals("Javatar", formParams.get("lastname").get(0));
+ return Response.status(Response.Status.OK).entity("Hello " + firstname + " " + lastname).build();
+ }
+
+ @POST
+ @Path("encoded")
+ public Response encoded(MultivaluedMap<String, String> formParams,
+ @Encoded @FormParam("firstname") String firstname,
+ @FormParam("lastname") String lastname) {
+ assertEquals(2, formParams.size());
+ assertEquals("George", formParams.get("firstname").get(0));
+ assertEquals("Javatar", formParams.get("lastname").get(0));
+ return Response.status(Response.Status.OK).entity("Hello " + firstname + " " + lastname).build();
+ }
+
+ }
+
+ @Path("form-ext")
+ public static class FormExtResource {
+
+ @Encoded @FormParam("firstname") String firstname;
+
+ @POST
+ @Path("encoded")
+ public Response encoded(MultivaluedMap<String, String> formParams,
+ @FormParam("lastname") String lastname) {
+ assertEquals(2, formParams.size());
+ assertEquals("George", formParams.get("firstname").get(0));
+ assertEquals("Javatar", formParams.get("lastname").get(0));
+ return Response.status(Response.Status.OK).entity("Hello " + firstname + " " + lastname).build();
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FormResource.class, FormExtResource.class);
+ }
+
+ @Test
+ public void testFormMultivaluedParam() {
+ Response result = call("/form/simple", "firstname=George&lastname=Javatar");
+ assertEquals(PREDEFINED_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testFormMultivaluedParamWithNull() {
+ Response result = call("/form/nullable", "firstname=George&firstname&lastname=Javatar");
+ assertEquals(PREDEFINED_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testFormMultivaluedParamMixedParamOrder() {
+ Response result = call("/form/mixed", "firstname=George&firstname&lastname=Javatar");
+ assertEquals(PREDEFINED_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testFormMultivaluedParamEncoded() {
+ Response result = call("/form/encoded", "firstname=George&lastname=Javatar");
+ assertEquals(PREDEFINED_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testFormMultivaluedParamExternalEncodedInjection() {
+ Response result = call("/form-ext/encoded", "firstname=George&lastname=Javatar");
+ assertEquals(PREDEFINED_RESPONSE, result.readEntity(String.class));
+ }
+
+ private Response call(String path, String entity) {
+ return target().path(path).request()
+ .post(Entity.entity(entity, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ }
+}
+
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GlobalNameBoundInterceptorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GlobalNameBoundInterceptorTest.java
new file mode 100644
index 0000000..5aaec35
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GlobalNameBoundInterceptorTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests name bound and global bound interceptors.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class GlobalNameBoundInterceptorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ InterceptorTestBound.class,
+ InterceptorGlobal.class,
+ PreMatchFilter.class,
+ TestResource.class,
+ TestExceptionMapper.class,
+ RequestFilter.class,
+ ReaderInterceptorGlobal.class,
+ ReaderInterceptorPostBound.class);
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface TestBound {}
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface PostBound {}
+
+ @Path("resource")
+ public static class TestResource {
+ @GET
+ @TestBound
+ public String get() {
+ return "get";
+ }
+
+ @GET
+ @Path("standard")
+ public String getStandard() {
+ return "ok";
+ }
+
+ @POST
+ @PostBound
+ @Path("postBound")
+ public String postBound(String str) {
+ return str;
+ }
+
+ @POST
+ @Path("postGlobal")
+ public String postGlobal(String str) {
+ return str;
+ }
+ }
+
+ public static class TestException extends RuntimeException {
+ public TestException(String message) {
+ super(message);
+ }
+ }
+
+ public static class TestExceptionMapper implements ExceptionMapper<TestException> {
+
+ @Override
+ public Response toResponse(TestException exception) {
+ return Response.ok("mapped-" + exception.getMessage()).build();
+ }
+ }
+
+
+ @PreMatching
+ public static class PreMatchFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if ("exception".equals(requestContext.getHeaderString("pre-filter"))) {
+ throw new TestException("(pre-matching-exception)");
+ } else if ("abort".equals(requestContext.getHeaderString("pre-filter"))) {
+ requestContext.abortWith(Response.ok("(pre-matching-abort)").build());
+ }
+ }
+ }
+
+ public static class RequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if ("exception".equals(requestContext.getHeaderString("request-filter"))) {
+ throw new TestException("(request-filter-exception)");
+ } else if ("abort".equals(requestContext.getHeaderString("request-filter"))) {
+ requestContext.abortWith(Response.ok("(request-filter-abort)").build());
+ }
+ }
+ }
+
+ @TestBound
+ @Priority(200)
+ public static class InterceptorTestBound implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ String entity = context.getEntity() + "-[test-bound]";
+ context.setEntity(entity);
+ context.proceed(); //Add one
+ }
+ }
+
+ @Priority(100)
+ public static class InterceptorGlobal implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ String entity = context.getEntity() + "-[global-bound]";
+ context.setEntity(entity);
+ context.proceed(); //Add one
+ }
+ }
+
+ @Priority(200)
+ public static class ReaderInterceptorGlobal implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final String entity = (String) context.proceed();
+ return entity + "-[global-reader-interceptor]";
+ }
+ }
+
+ @Priority(100)
+ @PostBound
+ public static class ReaderInterceptorPostBound implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final String entity = (String) context.proceed();
+ return entity + "-[post-reader-interceptor]";
+ }
+ }
+
+ @Test
+ public void testPrematchingException() {
+ final Response response = target("resource").request().header("pre-filter", "exception").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("mapped-(pre-matching-exception)-[global-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPrematchingAbort() {
+ final Response response = target("resource").request().header("pre-filter", "abort").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("(pre-matching-abort)-[global-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testRequestFilterException() {
+ final Response response = target("resource").request().header("request-filter", "exception").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("mapped-(request-filter-exception)-[global-bound]-[test-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testRequestFilterAbort() {
+ final Response response = target("resource").request().header("request-filter", "abort").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("(request-filter-abort)-[global-bound]-[test-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStandardResource() {
+ final Response response = target("resource/standard").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("ok-[global-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testTestResource() {
+ final Response response = target("resource").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("get-[global-bound]-[test-bound]", response.readEntity(String.class));
+ }
+
+
+ @Test
+ public void testPost() {
+ final Response response = target("resource/postGlobal").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("post-[global-reader-interceptor]-[global-bound]", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPostBound() {
+ final Response response = target("resource/postBound").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("post-[global-reader-interceptor]-[post-reader-interceptor]-[global-bound]",
+ response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GloballyNameBoundResourceFilterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GloballyNameBoundResourceFilterTest.java
new file mode 100644
index 0000000..da48b79
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GloballyNameBoundResourceFilterTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAX-RS global name-bound filter tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @see ResourceFilterTest
+ */
+public class GloballyNameBoundResourceFilterTest extends JerseyTest {
+
+ public static final String TEST_REQUEST_HEADER = "test-request-header";
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @GloballyBound
+ public static final class MyApplication extends ResourceConfig {
+ public MyApplication() {
+ super(
+ MyResource.class,
+ GloballyBoundRequestFilter.class,
+ GloballyBoundResponseFilter.class
+
+ );
+ }
+ }
+
+ @Test
+ public void testGlobalyBoundPostMatching() {
+ Response r = target("postMatching").request().get();
+ assertThat(r.getStatus(), equalTo(200));
+ assertThat(r.hasEntity(), is(true));
+ assertThat(r.readEntity(String.class), equalTo("requestFilter-method-responseFilter"));
+ }
+
+ // See JERSEY-1554
+ @Test
+ public void testGlobalyBoundPostMatchingRequestFilterNotInvokedOn404() {
+ Response r = target("notFound").request().get();
+ assertEquals(404, r.getStatus());
+ assertThat(r.hasEntity(), is(true));
+ assertThat(r.readEntity(String.class), equalTo("responseFilter"));
+ }
+
+ @Path("/")
+ public static class MyResource {
+
+ @Path("postMatching")
+ @GET
+ public String getPostMatching(@Context HttpHeaders headers) {
+ final String header = headers.getHeaderString(TEST_REQUEST_HEADER);
+ return header + "-method";
+ }
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface GloballyBound {
+ }
+
+ @GloballyBound
+ public static class GloballyBoundRequestFilter implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().putSingle(TEST_REQUEST_HEADER, "requestFilter");
+ }
+ }
+
+ @GloballyBound
+ public static class GloballyBoundResponseFilter implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ responseContext.setEntity(
+ responseContext.hasEntity() ? responseContext.getEntity() + "-responseFilter" : "responseFilter",
+ responseContext.getEntityAnnotations(),
+ responseContext.getMediaType());
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GrizzlyInjectionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GrizzlyInjectionTest.java
new file mode 100644
index 0000000..240fe6e
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GrizzlyInjectionTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.glassfish.grizzly.http.server.Request;
+import org.glassfish.grizzly.http.server.Response;
+
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Test for JERSEY-1170
+ *
+ * @author Paul Sandoz
+ */
+public class GrizzlyInjectionTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ @Path("/")
+ public static class Resource {
+ private final Request request;
+
+ public Resource(
+ @Context Request request,
+ @Context Response response) {
+ assertNotNull(request);
+ assertNotNull(response);
+ this.request = request;
+ }
+
+ @GET
+ public String get() {
+ return request.getMethod().getMethodString().toUpperCase();
+ }
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ final String s = target().path("/").request().get(String.class);
+ assertEquals("GET", s);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InitializationLoggingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InitializationLoggingTest.java
new file mode 100644
index 0000000..022ad21
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InitializationLoggingTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.LocalizationMessages;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class InitializationLoggingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+ return new ResourceConfig(A.class);
+ }
+
+ @Path("test")
+ public static class A {
+
+ @GET
+ public String get() {
+ return "test";
+ }
+ }
+
+ @Test
+ public void test() {
+ final Response r = target().path("test").request().get(Response.class);
+
+ assertTrue(r.readEntity(String.class).contains("test"));
+
+ boolean found = false;
+
+ for (LogRecord logRecord : getLoggedRecords()) {
+ if (logRecord.getMessage().contains(LocalizationMessages.LOGGING_APPLICATION_INITIALIZED())) {
+ found = true;
+ break;
+ }
+ }
+
+ assertTrue(found);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionManagerServerProviderTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionManagerServerProviderTest.java
new file mode 100644
index 0000000..d44521a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionManagerServerProviderTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.InjectionManagerProvider;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link InjectionManagerProvider}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class InjectionManagerServerProviderTest extends JerseyTest {
+
+ @Path("resource")
+ public static class TestResource {
+ @POST
+ @Path("feature")
+ @FeatureBound
+ public String echoFeature(String entity) {
+ return entity;
+ }
+
+
+ @POST
+ @Path("reader-interceptor")
+ @ReaderInterceptorBound
+ public String echoReaderInterceptor(String entity) {
+ return entity;
+ }
+
+ @POST
+ @Path("writer-interceptor")
+ @WriterInterceptorBound
+ public String echoWriterInterceptor(String entity) {
+ return entity;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(TestResource.class);
+ resourceConfig.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjectedService("hello")).to(MyInjectedService.class);
+ }
+ });
+ resourceConfig.register(new MyFeature());
+ resourceConfig.register(new MyReaderInterceptor());
+ resourceConfig.register(new MyWriterInterceptor());
+ return resourceConfig;
+ }
+
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface FeatureBound {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface ReaderInterceptorBound {
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface WriterInterceptorBound {
+ }
+
+
+ public static class MyInjectedService {
+ public final String name;
+
+ public MyInjectedService(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+
+ public static class MyFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(MyFeatureInterceptor.class);
+ return true;
+ }
+
+
+ @FeatureBound
+ public static class MyFeatureInterceptor implements WriterInterceptor {
+ private final String name;
+
+ @Inject
+ public MyFeatureInterceptor(MyInjectedService injectedService) {
+ this.name = injectedService.getName();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(((String) context.getEntity()) + "-interceptorfeature-" + name);
+ context.proceed();
+ }
+ }
+ }
+
+ @Test
+ public void testFeature() {
+ final Response response = target().path("resource/feature")
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-interceptorfeature-hello", response.readEntity(String.class));
+ }
+
+ @WriterInterceptorBound
+ public static class MyWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final InjectionManager serviceLocator = InjectionManagerProvider.getInjectionManager(context);
+ final MyInjectedService service = serviceLocator.getInstance(MyInjectedService.class);
+ context.setEntity(((String) context.getEntity()) + "-writer-interceptor-" + service.getName());
+ context.proceed();
+ }
+ }
+
+
+ @Test
+ public void testWriterInterceptor() {
+ final Response response = target().path("resource/writer-interceptor")
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-writer-interceptor-hello", response.readEntity(String.class));
+ }
+
+
+ @ReaderInterceptorBound
+ public static class MyReaderInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final Object entity = context.proceed();
+ if (!(entity instanceof String)) {
+ return entity;
+ }
+ final String stringEntity = (String) entity;
+ final InjectionManager serviceLocator = InjectionManagerProvider.getInjectionManager(context);
+ final MyInjectedService service = serviceLocator.getInstance(MyInjectedService.class);
+ return stringEntity + "-reader-interceptor-" + service.getName();
+ }
+ }
+
+ @Test
+ public void testReaderInterceptorInstance() {
+ final Response response = target().path("resource/reader-interceptor")
+ .request().post(Entity.entity("will-be-extended-by", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("will-be-extended-by-reader-interceptor-hello", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionTest.java
new file mode 100644
index 0000000..da84650
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InjectionTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.concurrent.Executors;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Injection E2E tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class InjectionTest extends JerseyTest {
+
+ @Path("injection")
+ public static class InjectionTestResource {
+
+ @DELETE
+ @Path("delete-path-param/{id}")
+ public String deletePathParam(String body, @PathParam("id") String id) {
+ return "deleted: " + id + "-" + body;
+ }
+
+ @DELETE
+ @Path("delete-path-param-async/{id}")
+ public void deletePathParam(String body, @PathParam("id") String id, @Suspended AsyncResponse ar) {
+ ar.resume("deleted: " + id + "-" + body);
+ }
+
+ @GET
+ @Path("async")
+ public void asyncGet(@Context final UriInfo uriInfo,
+ @Context final Request request,
+ @Context final HttpHeaders headers,
+ @Context final SecurityContext securityContext,
+ @Suspended final AsyncResponse response) {
+
+ // now suspend and resume later on with
+ Executors.newSingleThreadExecutor().submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ response.resume(String.format("base uri: %s\nheaders: %s\nmethod: %s\nprincipal: %s",
+ uriInfo.getBaseUriBuilder().build(),
+ headers.getRequestHeaders(),
+ request.getMethod(),
+ securityContext.getUserPrincipal()));
+ } catch (Throwable e) {
+ response.resume(e);
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(InjectionTestResource.class);
+ }
+
+ /**
+ * JERSEY-1711 reproducer.
+ *
+ * The test is ignored as it currently fails on the following:
+ * - HttpURLConnection throws a java.net.ProtocolException when trying to send request data with HTTP DELETE
+ * - Grizzly container ignores any DELETE request data and does not pass them to Jersey
+ *
+ * We would need to by-pass these issues in underlying layer to un-ignore the test.
+ */
+ @Test
+ @Ignore
+ public void testInjectionIntoDeleteMethod() {
+ Response response;
+
+ response = target("injection").path("delete-path-param/test").request()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
+ .method("DELETE", Entity.text("body"));
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertEquals("Unexpected response entity.", "deleted: test-body", response.readEntity(String.class));
+
+ response = target("injection").path("delete-path-param-async/test").request()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
+ .method("DELETE", Entity.text("body"));
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertEquals("Unexpected response entity.", "deleted: test-body", response.readEntity(String.class));
+ }
+
+ /**
+ * JERSEY-1761 reproducer.
+ *
+ * This is to make sure no proxy gets injected into async method parameters.
+ */
+ @Test
+ public void testAsyncMethodParamInjection() {
+
+ Response response = target("injection").path("async").request().get();
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertNotNull("Response is null.", response);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InputStreamResponseTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InputStreamResponseTest.java
new file mode 100644
index 0000000..feef6b4
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InputStreamResponseTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This is to make sure you can just pass an input stream to Jersey,
+ * where entity body data would be read from.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InputStreamResponseTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(InputStreamResource.class, WrappedInputStreamResource.class);
+ }
+
+ @Path("/directInputStream")
+ public static class InputStreamResource {
+
+ @GET
+ public InputStream get() {
+ return new ByteArrayInputStream("Josefka".getBytes());
+ }
+ }
+
+ @Test
+ public void testDirectInputStream() throws Exception {
+ final String s = target().path("directInputStream").request().get(String.class);
+
+ assertEquals("Josefka", s);
+ }
+
+ @Path("/responseWrappedInputStream")
+ public static class WrappedInputStreamResource {
+
+ @GET
+ public Response get() {
+ return Response.ok(new ByteArrayInputStream("Marie".getBytes()), MediaType.TEXT_PLAIN_TYPE).build();
+ }
+ }
+
+ @Test
+ public void testWrappedInputStream() throws Exception {
+ final Response response = target().path("responseWrappedInputStream").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+ assertEquals("Marie", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorHttpHeadersInjectionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorHttpHeadersInjectionTest.java
new file mode 100644
index 0000000..12be8fc
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorHttpHeadersInjectionTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for JERSEY-1545.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InterceptorHttpHeadersInjectionTest extends JerseyTest {
+
+ static final String WriterHEADER = "custom-writer-header";
+ static final String ReaderHEADER = "custom-reader-header";
+ static final String RawCONTENT = "SIMPLE";
+
+ @Provider
+ public static class InjectedWriterInterceptor implements WriterInterceptor {
+
+ @Context
+ HttpHeaders headers;
+
+ // Replace content with WriterHEADER header value if corresponding header is seen.
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final String writerHeaderValue = headers.getHeaderString(WriterHEADER);
+
+ if (writerHeaderValue != null) {
+ context.getOutputStream().write(writerHeaderValue.getBytes());
+ }
+
+ context.proceed();
+ }
+ }
+
+ @Provider
+ public static class InjectedReaderInterceptor implements ReaderInterceptor {
+
+ @Context
+ HttpHeaders headers;
+
+ // Replace content with ReaderHEADER header value if corresponding header is seen.
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final String readerHeaderValue = headers.getHeaderString(ReaderHEADER);
+
+ if (readerHeaderValue != null) {
+ return readerHeaderValue;
+ }
+ return context.proceed();
+ }
+ }
+
+ @Path("/")
+ public static class SimpleResource {
+
+ @GET
+ public String getIt() {
+ return RawCONTENT;
+ }
+
+ @POST
+ public String echo(String message) {
+ return message;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SimpleResource.class, InjectedWriterInterceptor.class, InjectedReaderInterceptor.class);
+ }
+
+ // No interceptor should tweak the content if there is not header present.
+ private void _checkRawGet() {
+ final String result = target().request().get(String.class);
+ assertThat(result, containsString(RawCONTENT));
+ }
+
+ @Test
+ public void testWriter() throws Exception {
+ _checkRawGet();
+ _checkWriterInterceptor("writer-one");
+ _checkWriterInterceptor("writer-two");
+ }
+
+ // set WriterHEADER header and check the same value is returned back
+ private void _checkWriterInterceptor(final String headerValue) {
+ final String result = target().request().header(WriterHEADER, headerValue).get(String.class);
+ assertThat(result, containsString(headerValue));
+ }
+
+ @Test
+ public void testReader() throws Exception {
+ _checkRawEcho();
+ _checkReaderInterceptor("reader-one");
+ _checkReaderInterceptor("reader-two");
+ }
+
+ // No interceptor should tweak the content if there is not header present.
+ private void _checkRawEcho() {
+ final String rawResult = target().request().post(Entity.text(RawCONTENT), String.class);
+ assertThat(rawResult, containsString(RawCONTENT));
+ }
+
+ // set ReaderHEADER header and check the same value is returned back
+ private void _checkReaderInterceptor(String headerValue) {
+ final String result = target().request().header(ReaderHEADER, headerValue).post(Entity.text(RawCONTENT), String.class);
+ assertThat(result, containsString(headerValue));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorNameAndDynamicBindingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorNameAndDynamicBindingTest.java
new file mode 100644
index 0000000..d9942c7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/InterceptorNameAndDynamicBindingTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InterceptorNameAndDynamicBindingTest extends JerseyTest {
+
+ static final String ENTITY = "ENTITY";
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ super.configureClient(config);
+ }
+
+ abstract static class PrefixAddingReaderInterceptor implements ReaderInterceptor {
+
+ public PrefixAddingReaderInterceptor() {
+ }
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(
+ new SequenceInputStream(new ByteArrayInputStream(getPrefix().getBytes()), context.getInputStream()));
+ return context.proceed();
+ }
+
+ abstract String getPrefix();
+ }
+
+ abstract static class PrefixAddingWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.getOutputStream().write(getPrefix().getBytes());
+ context.proceed();
+ }
+
+ abstract String getPrefix();
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ static @interface NameBoundReader {
+ }
+
+ @NameBoundReader
+ @Priority(40)
+ static class NameBoundReaderInterceptor extends PrefixAddingReaderInterceptor {
+
+ @Override
+ String getPrefix() {
+ return "nameBoundReader";
+ }
+ }
+
+ @Priority(60)
+ static class DynamicallyBoundReaderInterceptor extends PrefixAddingReaderInterceptor {
+
+ @Override
+ String getPrefix() {
+ return "dynamicallyBoundReader";
+ }
+ }
+
+ @NameBinding
+ @Priority(40)
+ @Retention(RetentionPolicy.RUNTIME)
+ static @interface NameBoundWriter {
+ }
+
+ @NameBoundWriter
+ public static class NameBoundWriterInterceptor extends PrefixAddingWriterInterceptor {
+
+ @Override
+ String getPrefix() {
+ return "nameBoundWriter";
+ }
+ }
+
+ @Priority(20)
+ public static class DynamicallyBoundWriterInterceptor extends PrefixAddingWriterInterceptor {
+
+ @Override
+ String getPrefix() {
+ return "dynamicallyBoundWriter";
+ }
+ }
+
+ @Path("method")
+ public static class MethodBindingResource {
+
+ @Path("dynamicallyBoundWriter")
+ @GET
+ public String getDynamicallyBoundWriter() {
+ return ENTITY;
+ }
+
+ @Path("nameBoundWriter")
+ @GET
+ @NameBoundWriter
+ public String getNameBoundWriter() {
+ return ENTITY;
+ }
+
+ @Path("dynamicallyBoundReader")
+ @POST
+ public String postDynamicallyBoundReader(String input) {
+ return input;
+ }
+
+ @Path("nameBoundReader")
+ @POST
+ @NameBoundReader
+ public String postNameBoundReader(String input) {
+ return input;
+ }
+ }
+
+ @Path("class")
+ @NameBoundWriter
+ public static class ClassBindingResource {
+
+ @Path("nameBoundWriter")
+ @GET
+ public String getNameBoundWriter() {
+ return ENTITY;
+ }
+
+ @Path("nameBoundReader")
+ @POST
+ public String postNameBoundReader(String input) {
+ return input;
+ }
+ }
+
+ @Path("mixed")
+ @NameBoundWriter
+ public static class MixedBindingResource {
+
+ @Path("nameBoundWriterDynamicReader")
+ @POST
+ public String postNameBoundWrDynamicallyBoundReader(String input) {
+ return input;
+ }
+
+ @Path("nameBoundWriterDynamicWriterNameBoundReader")
+ @POST
+ @NameBoundReader
+ public String postNameBoundReWrDynamicallyBoundWriter(String input) {
+ return input;
+ }
+ }
+
+ static final Pattern ReaderMETHOD = Pattern.compile(".*Dynamically.*Reader");
+ static final Pattern WriterMETHOD = Pattern.compile(".*Dynamically.*Writer");
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MethodBindingResource.class, ClassBindingResource.class,
+ MixedBindingResource.class, NameBoundReaderInterceptor.class, NameBoundWriterInterceptor.class).registerInstances(
+ new DynamicFeature() {
+
+ @Override
+ public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
+ if (ReaderMETHOD.matcher(resourceInfo.getResourceMethod().getName()).matches()) {
+ context.register(DynamicallyBoundReaderInterceptor.class);
+ }
+ }
+ },
+ new DynamicFeature() {
+
+ @Override
+ public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
+ if (WriterMETHOD.matcher(resourceInfo.getResourceMethod().getName()).matches()) {
+ context.register(DynamicallyBoundWriterInterceptor.class);
+ }
+ }
+ }
+ );
+ }
+
+ @Test
+ public void testNameBoundReaderOnMethod() {
+ _testReader("method", "nameBoundReader");
+ }
+
+ @Test
+ public void testNameBoundWriterOnMethod() {
+ _testWriter("method", "nameBoundWriter");
+ }
+
+ @Test
+ public void testNameBoundReaderOnClass() {
+ _testReader("class", "nameBoundReader", "nameBoundWriterENTITY");
+ }
+
+ @Test
+ public void testNameBoundWriterOnClass() {
+ _testWriter("class", "nameBoundWriter");
+ }
+
+ @Test
+ public void testDynamicallyBoundReaderOnMethod() {
+ _testReader("method", "dynamicallyBoundReader");
+ }
+
+ @Test
+ public void testDynamicallyBoundWriterOnMethod() {
+ _testWriter("method", "dynamicallyBoundWriter");
+ }
+
+ @Test
+ public void testDynamicReaderOnMethodNamedWriterOnClass() {
+ _testReader("mixed", "nameBoundWriterDynamicReader", "nameBoundWriterdynamicallyBoundReaderENTITY");
+ }
+
+ @Test
+ public void testNameBoundWriterDynamicWriterNameBoundReader() {
+ _testReader("mixed", "nameBoundWriterDynamicWriterNameBoundReader",
+ "dynamicallyBoundWriternameBoundWriternameBoundReaderENTITY");
+ }
+
+ private void _testReader(String root, String id) {
+ _testReader(root, id, id + ENTITY);
+ }
+
+ private void _testReader(String root, String id, String expected) {
+ Response r = target(root + "/" + id).request().post(Entity.entity(ENTITY, MediaType.TEXT_PLAIN));
+ assertEquals(200, r.getStatus());
+ assertEquals(expected, r.readEntity(String.class));
+ }
+
+ private void _testWriter(String root, String id) {
+ _testWriter(root, id, id + ENTITY);
+ }
+
+ private void _testWriter(String root, String id, String expected) {
+ Response r = target(root + "/" + id).request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals(expected, r.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java
new file mode 100644
index 0000000..b043227
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Type;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.server.ClientBinding;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test, that managed client uses the custom executor service.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class ManagedClientExecutorTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(TestResource.class);
+ }
+
+ /**
+ * Test JAX-RS resource.
+ */
+ @Path(value = "/test")
+ public static class TestResource {
+ /**
+ * Invoke an asynchronous request using the injected managed client.
+ * <p>
+ * The client is configured to use custom message body reader, that checks its worker thread and replaces the original
+ * response with the transfer object containing the thread name. The name is than used to identify if the correct
+ * (custom) executor service is used.
+ *
+ * @return name of the thread, that executed the asynchronous request
+ */
+ @GET
+ @Path("executor")
+ public String managedClientWithExecutor(@ClientA @Uri("http://localhost:9998/") WebTarget target)
+ throws ExecutionException, InterruptedException {
+ Future<ThreadName> nameFuture = target.path("test/dummy").request().async().get(ThreadName.class);
+ return nameFuture.get().getThreadName();
+ }
+
+ /**
+ * Invoke an asynchronous request using the injected managed client.
+ * <p>
+ * The client is configured to use custom message body reader, that uses injected scheduled executor service and
+ * schedules a task, that checks its worker thread name, then it does the same with the injected scheduled executor
+ * service provider (to check that both injection approaches produce same result) and returns both thread names in a
+ * transfer objects. The names are than used to identify if the correct (custom) scheduled executor service(s) is (are)
+ * used.
+ *
+ * @return names of the threads, that executed the scheduled tasks
+ */
+ @GET
+ @Path("scheduledExecutor")
+ public String managedClientWithScheduledExecutor(@ClientA @Uri("http://localhost:9998/") WebTarget target)
+ throws ExecutionException, InterruptedException {
+ Future<SchedulerThreadName> namesFuture = target.path("test/dummy").request().async().get(SchedulerThreadName.class);
+ return namesFuture.get().getThreadNameFromService() + " " + namesFuture.get().getThreadNameFromProvider();
+ }
+
+ /**
+ * Dummy method, that is invoked by the managed client.
+ *
+ * @return dummy response, does not really matter
+ */
+ @GET
+ @Path("dummy")
+ public String dummyMethod() {
+ return "nothing";
+ }
+ }
+
+ /**
+ * Managed client binding.
+ */
+ @ClientBinding(configClass = MyClientAConfig.class)
+ @Documented
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+ public @interface ClientA {
+ }
+
+ /**
+ * Managed client config.
+ */
+ public static class MyClientAConfig extends ClientConfig {
+
+ public MyClientAConfig() {
+ final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+ .setNameFormat("foo-executor-service-%d")
+ .build());
+
+ final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
+ .setNameFormat("bar-executor-service")
+ .build());
+
+ this.register(new ThreadNameReader())
+ .register(SchedulerThreadNameReader.class)
+ .executorService(executor)
+ .scheduledExecutorService(scheduler);
+ }
+ }
+
+ /**
+ * Transfer object for executor service name.
+ */
+ static class ThreadName {
+ private String threadName;
+
+ ThreadName(String threadName) {
+ this.threadName = threadName;
+ }
+
+ String getThreadName() {
+ return threadName;
+ }
+ }
+
+ /**
+ * Transfer object for scheduled executor service(s) name(s), both resolved from directly injected service and via provider.
+ */
+ static class SchedulerThreadName {
+ private String threadNameFromService;
+ private String threadNameFromProvider;
+
+ SchedulerThreadName(String threadNameFromService, String threadNameFromProvider) {
+ this.threadNameFromService = threadNameFromService;
+ this.threadNameFromProvider = threadNameFromProvider;
+ }
+
+ String getThreadNameFromService() {
+ return threadNameFromService;
+ }
+
+ String getThreadNameFromProvider() {
+ return threadNameFromProvider;
+ }
+ }
+
+ /**
+ * Custom reader, that checks its own thread's name and returns it as an entity.
+ */
+ public static class ThreadNameReader implements MessageBodyReader<ThreadName> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public ThreadName readFrom(Class<ThreadName> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ return new ThreadName(Thread.currentThread().getName());
+ }
+ }
+
+ /**
+ * Custom reader, that schedules one task on each injected scheduler (directly and via provider) and returns the names of
+ * the threads that executed those tasks as an entity.
+ */
+ public static class SchedulerThreadNameReader implements MessageBodyReader<SchedulerThreadName> {
+
+ @Inject
+ ScheduledExecutorServiceProvider injectedProvider;
+
+ @Inject
+ ScheduledExecutorService injectedService;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public SchedulerThreadName readFrom(Class<SchedulerThreadName> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ AtomicReference<String> nameFromService = new AtomicReference<>();
+ AtomicReference<String> nameFromProvider = new AtomicReference<>();
+ CountDownLatch cdl = new CountDownLatch(2);
+
+ injectedService.schedule(() -> {
+ nameFromService.set(Thread.currentThread().getName());
+ cdl.countDown();
+ }, 1, TimeUnit.MILLISECONDS);
+
+ injectedProvider.getExecutorService().schedule(() -> {
+ nameFromProvider.set(Thread.currentThread().getName());
+ cdl.countDown();
+ }, 1, TimeUnit.MILLISECONDS);
+
+ try {
+ cdl.await(200, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ nameFromService.set("failed");
+ nameFromProvider.set("failed");
+ }
+
+ return new SchedulerThreadName(nameFromService.get(), nameFromProvider.get());
+ }
+ }
+
+ @Test
+ public void testManagedClientExecutor() {
+ final String response = target().path("test/executor").request().get(String.class);
+ Assert.assertEquals("foo-executor-service-0", response);
+ }
+
+ @Test
+ public void testManagedClientScheduledExecutor() {
+ final String response = target().path("test/scheduledExecutor").request().get(String.class);
+ Assert.assertEquals("bar-executor-service bar-executor-service", response);
+ System.out.println(response);
+ }
+}
+
+
+
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MessageBodyProvidersExceptionsTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MessageBodyProvidersExceptionsTest.java
new file mode 100644
index 0000000..5036151
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MessageBodyProvidersExceptionsTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JERSEY-2500 reproducer test.
+ *
+ * Tests, that correct exceptions are thrown in case no MessageBodyProvider was matched on server.
+ *
+ * - InternalServerErrorException for MBW (JSR339, chapter 4.2.2, step 7)
+ * - NotSupportedException for MBR (JSR339, chapter 4.2.1, step 6)
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MessageBodyProvidersExceptionsTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(MessageBodyProvidersExceptionsTest.class.getName());
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ Resource.class,
+ WebAppExceptionMapper.class
+ );
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ @Path("write")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Resource failOnWrite() {
+ return this;
+ }
+
+ @POST
+ @Path("read")
+ @Consumes("foo/bar")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String failOnRead() {
+ return "this-should-never-be-returned";
+ }
+ }
+
+ @Provider
+ public static class WebAppExceptionMapper implements ExceptionMapper<WebApplicationException> {
+
+ @Override
+ public Response toResponse(WebApplicationException exception) {
+ LOGGER.fine("ExceptionMapper was invoked.");
+ // return the exception class name as an entity for further comparison
+ return Response.status(200).header("writer-exception", "after-first-byte").entity(exception.getClass().getName())
+ .build();
+ }
+ }
+
+ @Test
+ public void testReaderThrowsCorrectException() {
+ Response response = target().path("resource/write").request(MediaType.TEXT_PLAIN).get();
+ assertEquals(200, response.getStatus());
+ String resString = response.readEntity(String.class);
+ // no MBW should have been found, InternalServerErrorException expected
+ assertEquals("javax.ws.rs.InternalServerErrorException", resString);
+ }
+
+ @Test
+ public void testWriterThrowsCorrectException() {
+ Response response = target().path("resource/read").request().post(Entity.entity("Hello, world", "text/plain"));
+ assertEquals(200, response.getStatus());
+ String resString = response.readEntity(String.class);
+ // no MBR should have been found, NotSupportedException expected
+ assertEquals("javax.ws.rs.NotSupportedException", resString);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupDisabledTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupDisabledTest.java
new file mode 100644
index 0000000..44c514a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupDisabledTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+import org.junit.Test;
+
+/**
+ * Property {@link ServerProperties#METAINF_SERVICES_LOOKUP_DISABLE} IS set.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class MetainfServicesLookupDisabledTest extends AbstractDisableMetainfServicesLookupTest {
+
+ @Test
+ public void testGet() throws Exception {
+ testGet(500, 415);
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = (ResourceConfig) super.configure();
+ resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
+
+ return resourceConfig;
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupEnabledTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupEnabledTest.java
new file mode 100644
index 0000000..a558f11
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/MetainfServicesLookupEnabledTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import org.junit.Test;
+
+/**
+ * Property {@link org.glassfish.jersey.server.ServerProperties#METAINF_SERVICES_LOOKUP_DISABLE} is NOT set.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class MetainfServicesLookupEnabledTest extends AbstractDisableMetainfServicesLookupTest {
+
+ @Test
+ public void testGet() throws Exception {
+ testGet(200, 200);
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ModelProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ModelProcessorTest.java
new file mode 100644
index 0000000..e0c1c8b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ModelProcessorTest.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ExtendedResourceContext;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.model.ModelProcessor;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceMethod;
+import org.glassfish.jersey.server.model.ResourceModel;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test model processor.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+@RunWith(ConcurrentRunner.class)
+public class ModelProcessorTest extends JerseyTest {
+
+ public static class ModelProcessorFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(SimpleModelProcessor.class);
+ return true;
+ }
+
+ private static class SimpleModelProcessor implements ModelProcessor {
+
+ @Override
+ public ResourceModel processResourceModel(ResourceModel resourceModel, Configuration configuration) {
+ ResourceModel.Builder modelBuilder = new ResourceModel.Builder(false);
+ final Resource modelResource = Resource.from(ModelResource.class);
+ modelBuilder.addResource(modelResource);
+
+ for (final Resource resource : resourceModel.getRootResources()) {
+ Resource newResource = enhanceResource(resource);
+ modelBuilder.addResource(newResource);
+ }
+
+ return modelBuilder.build();
+ }
+
+ private Resource enhanceResource(final Resource resource) {
+ final Resource.Builder resBuilder = Resource.builder(resource);
+ boolean optionsFound = false;
+ for (ResourceMethod resourceMethod : resource.getResourceMethods()) {
+ if (resourceMethod.getHttpMethod().equals("OPTIONS")) {
+ optionsFound = true;
+ }
+ }
+ if (!optionsFound) {
+
+ resBuilder.addMethod("OPTIONS").produces(MediaType.TEXT_PLAIN_TYPE)
+ .handledBy(new Inflector<ContainerRequestContext, String>() {
+ @Override
+ public String apply(ContainerRequestContext containerRequestContext) {
+ return resource.getPath();
+ }
+ });
+ }
+
+ final Inflector<ContainerRequestContext, Object> inflector = new Inflector<ContainerRequestContext, Object>() {
+
+ @Override
+ public Object apply(ContainerRequestContext requestContext) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("my-resource:");
+ final String path = resource.getPath();
+ sb.append(path == null ? "<no-path>" : path + ",");
+
+ for (ResourceMethod resourceMethod : sortResourceMethods(resource.getResourceMethods())) {
+ sb.append(resourceMethod.getHttpMethod()).append("=").append("")
+ .append(resourceMethod.getInvocable().getHandlingMethod().getName()).append("|");
+ }
+ return sb.toString();
+ }
+ };
+
+ resBuilder.addChildResource("my-resource")
+ .addMethod("GET")
+ .produces(MediaType.TEXT_PLAIN_TYPE)
+ .handledBy(inflector).build();
+
+ return resBuilder.build();
+ }
+
+ @Override
+ public ResourceModel processSubResource(ResourceModel subResource, Configuration configuration) {
+ final Resource resource = enhanceResource(subResource.getResources().get(0));
+ return new ResourceModel.Builder(true).addResource(resource).build();
+ }
+ }
+
+ @Path("model")
+ public static class ModelResource {
+
+ @Context
+ ExtendedResourceContext resourceContext;
+
+ @GET
+ public String get() {
+ final ResourceModel resourceModel = resourceContext.getResourceModel();
+ StringBuilder sb = new StringBuilder();
+ List<Resource> sortedResources = resourceModel.getRootResources();
+ Collections.sort(sortedResources, new Comparator<Resource>() {
+ @Override
+ public int compare(Resource o1, Resource o2) {
+ final String path1 = o1.getPath() == null ? "" : o1.getPath();
+ final String path2 = o2.getPath() == null ? "" : o2.getPath();
+ return path1.compareTo(path2);
+ }
+ });
+ for (Resource resource : sortedResources) {
+ final String path = resource.getPath();
+ sb.append(path == null ? "<no-path>" : path).append("|");
+ }
+
+ return sb.toString();
+ }
+ }
+ }
+
+ private static List<ResourceMethod> sortResourceMethods(List<ResourceMethod> resourceMethods) {
+ List<ResourceMethod> newList = new ArrayList<>(resourceMethods);
+ Collections.sort(newList, (o1, o2) -> o1.getHttpMethod().compareTo(o2.getHttpMethod()));
+ return newList;
+ }
+
+ @Path("a")
+ public static class ResourceA {
+
+ @GET
+ public String getFromA() {
+ return "a-get";
+ }
+
+ @POST
+ public String postFromA(String entity) {
+ return "a-post";
+ }
+
+ @GET
+ @Path("child")
+ public String getChild() {
+ return "a-child-get";
+ }
+
+ @Path("locator")
+ public SubResource locatorFromA() {
+ return new SubResource();
+ }
+ }
+
+ public static class SubResource {
+
+ @GET
+ public String getFromSubResource() {
+ return "sub-get";
+ }
+ }
+
+ @Path("b")
+ public static class ResourceB {
+
+ @GET
+ public String getFromB() {
+ return "b-get";
+ }
+
+ @OPTIONS
+ public String optionsFromB() {
+ return "b-options";
+ }
+
+ @Path("locator")
+ public SubResource locatorFromB() {
+ return new SubResource();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(ResourceA.class, ResourceB.class, ModelProcessorFeature.class);
+ resourceConfig.property(ServerProperties.WADL_FEATURE_DISABLE, true);
+ return resourceConfig;
+ }
+
+ @Test
+ public void testResourceAGet() {
+ Response response = target("/a").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("a-get", entity);
+ }
+
+ @Test
+ public void testResourceAPost() {
+ Response response = target("/a").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("a-post", entity);
+ }
+
+ @Test
+ public void testResourceAOptions() {
+ Response response = target("/a").request(MediaType.TEXT_PLAIN_TYPE).options();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("a", entity);
+ }
+
+ @Test
+ public void testResourceAChildGet() {
+ Response response = target("/a/child").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("a-child-get", entity);
+ }
+
+ @Test
+ public void testResourceALocatorGet() {
+ Response response = target("/a/locator").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("sub-get", entity);
+ }
+
+ @Test
+ public void testResourceALocatorOptions() {
+ Response response = target("/a/locator").request(MediaType.TEXT_PLAIN_TYPE).options();
+ assertEquals(204, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("", entity);
+ }
+
+ @Test
+ public void testResourceBGet() {
+ Response response = target("/b").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("b-get", entity);
+ }
+
+ @Test
+ public void testResourceBOptions() {
+ Response response = target("/b").request(MediaType.TEXT_PLAIN_TYPE).options();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("b-options", entity);
+ }
+
+ @Test
+ public void testResourceBLocatorGet() {
+ Response response = target("/b/locator").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("sub-get", entity);
+ }
+
+ @Test
+ public void testResourceBLocatorOptions() {
+ Response response = target("/b/locator").request(MediaType.TEXT_PLAIN_TYPE).options();
+ assertEquals(204, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("", entity);
+ }
+
+ @Test
+ public void testResourceAMyResource() {
+ Response response = target("/a/my-resource").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("my-resource:a,GET=getFromA|POST=postFromA|", entity);
+ }
+
+ @Test
+ public void testResourceALocatorMyResource() {
+ Response response = target("/a/locator/my-resource").request(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("my-resource:<no-path>GET=getFromSubResource|", entity);
+ }
+
+ @Test
+ public void testResourceBMyResource() {
+ Response response = target("/b/my-resource").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("my-resource:b,GET=getFromB|OPTIONS=optionsFromB|", entity);
+ }
+
+ @Test
+ public void testInfo() {
+ Response response = target("/model").request().get();
+ assertEquals(200, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("a|b|model|", entity);
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/NameBindingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/NameBindingTest.java
new file mode 100644
index 0000000..02a740c
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/NameBindingTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test-suite ensuring the correct functionality of name binding.
+ *
+ * @author Miroslav Fuksa
+ * @author Michal Gajdos
+ */
+@RunWith(ConcurrentRunner.class)
+public class NameBindingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, FooResource.class, BarResource.class, FooBarResource.class, FooFilter.class,
+ BarFilter.class, FooBarFilter.class, PreMatchingFooFilter.class);
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ public String noBinding() {
+ return "noBinding";
+ }
+
+ @GET
+ @FooBinding
+ @Path("foo")
+ public String foo() {
+ return "foo";
+ }
+
+ @GET
+ @BarBinding
+ @Path("bar")
+ public String bar() {
+ return "bar";
+ }
+
+ @GET
+ @FooBinding
+ @BarBinding
+ @Path("foobar")
+ public String foobar() {
+ return "foobar";
+ }
+
+ @GET
+ @Path("preMatchingNameBinding")
+ public String preMatchingNameBinding(@HeaderParam("header") @DefaultValue("bar") final String header) {
+ return header;
+ }
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface FooBinding {
+
+ }
+
+ @NameBinding
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @Retention(value = RetentionPolicy.RUNTIME)
+ public static @interface BarBinding {
+
+ }
+
+ @FooBinding
+ public static class FooFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws
+ IOException {
+ responseContext.getHeaders().add(this.getClass().getSimpleName(), "called");
+ }
+ }
+
+ @PreMatching
+ @FooBinding
+ public static class PreMatchingFooFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().putSingle("header", "foo");
+ }
+ }
+
+ @BarBinding
+ public static class BarFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws
+ IOException {
+ responseContext.getHeaders().add(this.getClass().getSimpleName(), "called");
+ }
+ }
+
+ @FooBinding
+ @BarBinding
+ public static class FooBarFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws
+ IOException {
+ responseContext.getHeaders().add(this.getClass().getSimpleName(), "called");
+ }
+ }
+
+ private static final Set<Class<?>> FILTERS = initialize();
+
+ private static Set<Class<?>> initialize() {
+ final Set<Class<?>> set = new HashSet<>();
+ set.add(FooFilter.class);
+ set.add(BarFilter.class);
+ set.add(FooBarFilter.class);
+ return set;
+ }
+
+ private void checkCalled(final Response response, final Class<?>... filtersThatShouldBeCalled) {
+ final Set<Class<?>> positiveFilters = Arrays.stream(filtersThatShouldBeCalled).collect(Collectors.toSet());
+ for (final Class<?> filter : FILTERS) {
+ if (positiveFilters.contains(filter)) {
+ assertEquals("Filter '" + filter.getSimpleName() + "' should be called.", "called", response.getHeaders()
+ .getFirst(filter.getSimpleName()));
+ } else {
+ assertNull("Filter '" + filter.getSimpleName() + "' should not be called.", response.getHeaders().get(filter
+ .getSimpleName()));
+ }
+ }
+ }
+
+ private Response _getResponse(final String path) {
+ final Response response = target().path(path).request().get();
+ assertEquals(200, response.getStatus());
+ return response;
+ }
+
+ @Test
+ public void testResourceNoBinding() {
+ checkCalled(_getResponse("resource"));
+ }
+
+ @Test
+ public void testResourceFooBinding() {
+ checkCalled(_getResponse("resource/foo"), FooFilter.class);
+ }
+
+ /**
+ * Reproducer for JERSEY-2739. Name bound annotation on a pre-matching filter should be ignored and the filter should be
+ * invoked for each resource method (globally).
+ */
+ @Test
+ public void preMatchingNameBinding() {
+ final Response response = _getResponse("resource/preMatchingNameBinding");
+
+ // Request filter - applied, even when the filter is name bound and the resource method is not.
+ assertThat("Name binding on a @PreMatching filter not ignored.", response.readEntity(String.class), is("foo"));
+ }
+
+ @Test
+ public void testResourceBarBinding() {
+ checkCalled(_getResponse("resource/bar"), BarFilter.class);
+ }
+
+ @Test
+ public void testResourceFooBarBinding() {
+ checkCalled(_getResponse("resource/foobar"), FooFilter.class, BarFilter.class, FooBarFilter.class);
+ }
+
+ @Path("foo-resource")
+ @FooBinding
+ public static class FooResource extends Resource {
+
+ }
+
+ @Test
+ public void testFooResourceNoBinding() {
+ checkCalled(_getResponse("foo-resource"), FooFilter.class);
+ }
+
+ @Test
+ public void testFooResourceFooBinding() {
+ checkCalled(_getResponse("foo-resource/foo"), FooFilter.class);
+ }
+
+ @Test
+ public void testFooResourceBarBinding() {
+ checkCalled(_getResponse("foo-resource/bar"), FooFilter.class, BarFilter.class, FooBarFilter.class);
+ }
+
+ @Test
+ public void testFooResourceFooBarBinding() {
+ checkCalled(_getResponse("foo-resource/foobar"), FooFilter.class, BarFilter.class, FooBarFilter.class);
+ }
+
+ @Path("bar-resource")
+ @BarBinding
+ public static class BarResource extends Resource {
+
+ }
+
+ @Test
+ public void testBarResourceNoBinding() {
+ checkCalled(_getResponse("bar-resource"), BarFilter.class);
+ }
+
+ @Test
+ public void testBarResourceFooBinding() {
+ checkCalled(_getResponse("bar-resource/foo"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+ @Test
+ public void testBarResourceBarBinding() {
+ checkCalled(_getResponse("bar-resource/bar"), BarFilter.class);
+ }
+
+ @Test
+ public void testBarResourceFooBarBinding() {
+ checkCalled(_getResponse("bar-resource/foobar"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+ @Path("foobar-resource")
+ @BarBinding
+ @FooBinding
+ public static class FooBarResource extends Resource {
+
+ }
+
+ @Test
+ public void testFooBarResourceNoBinding() {
+ checkCalled(_getResponse("foobar-resource"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+ @Test
+ public void testFooBarResourceFooBinding() {
+ checkCalled(_getResponse("foobar-resource/foo"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+ @Test
+ public void testFooBarResourceBarBinding() {
+ checkCalled(_getResponse("foobar-resource/bar"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+ @Test
+ public void testFooBarResourceFooBarBinding() {
+ checkCalled(_getResponse("foobar-resource/foobar"), BarFilter.class, FooFilter.class, FooBarFilter.class);
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterPriorityTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterPriorityTest.java
new file mode 100644
index 0000000..0105506
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterPriorityTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.typeCompatibleWith;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ParamConverterPriorityTest extends JerseyTest {
+
+ private static final List<Class<? extends ParamConverterProvider>> CONVERTER_PROVIDER_CALL_ORDER = new ArrayList<>();
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ParamConverterPriorityResource.class,
+ MyParamConverterProvider1.class,
+ MyParamConverterProvider2.class,
+ MyParamConverterProvider3.class);
+ }
+
+ @Test
+ public void test() {
+ Response response = target().queryParam("test", "value").request().get();
+
+ assertThat(CONVERTER_PROVIDER_CALL_ORDER.size(), greaterThanOrEqualTo(3));
+ assertThat(CONVERTER_PROVIDER_CALL_ORDER.get(0), typeCompatibleWith(MyParamConverterProvider2.class));
+ assertThat(CONVERTER_PROVIDER_CALL_ORDER.get(1), typeCompatibleWith(MyParamConverterProvider1.class));
+ assertThat(CONVERTER_PROVIDER_CALL_ORDER.get(2), typeCompatibleWith(MyParamConverterProvider3.class));
+ }
+
+ @Path("/")
+ public static class ParamConverterPriorityResource {
+
+ @GET
+ public String get(@QueryParam("test") String param) {
+ return param;
+ }
+ }
+
+ @Priority(200)
+ public static class MyParamConverterProvider1 implements ParamConverterProvider {
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ CONVERTER_PROVIDER_CALL_ORDER.add(this.getClass());
+ return null;
+ }
+ }
+
+ @Priority(100)
+ public static class MyParamConverterProvider2 implements ParamConverterProvider {
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ CONVERTER_PROVIDER_CALL_ORDER.add(this.getClass());
+ return null;
+ }
+ }
+
+ @Priority(300)
+ public static class MyParamConverterProvider3 implements ParamConverterProvider {
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ CONVERTER_PROVIDER_CALL_ORDER.add(this.getClass());
+ return null;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterTest.java
new file mode 100644
index 0000000..6ef6bc6
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ParamConverterTest.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests {@link ParamConverter param converters} as e2e test.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ParamConverterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, MyParamProvider.class, MyStringParamProvider.class);
+ }
+
+ @Test
+ public void testMyBeanParam() {
+ Form form = new Form();
+ form.param("form", "formParam");
+ final Response response = target()
+ .path("resource/myBean").path("pathParam")
+ .matrixParam("matrix", "matrixParam")
+ .queryParam("query", "queryParam")
+ .request()
+ .header("header", "headerParam")
+ .cookie("cookie", "cookieParam")
+ .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+
+ final String str = response.readEntity(String.class);
+ assertEquals("*pathParam*_*matrixParam*_*queryParam*_*headerParam*_*cookieParam*_*formParam*", str);
+ }
+
+ @Test
+ public void testListOfMyBeanParam() {
+ final Response response = target().path("resource/myBean/list")
+ .queryParam("q", "A")
+ .queryParam("q", "B")
+ .queryParam("q", "C")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*A**B**C*", str);
+ }
+
+ @Test
+ public void testSetOfMyBeanParam() {
+ final Response response = target().path("resource/myBean/set")
+ .queryParam("q", "A")
+ .queryParam("q", "B")
+ .queryParam("q", "C")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertThat(str, containsString("*A*"));
+ assertThat(str, containsString("*B*"));
+ assertThat(str, containsString("*C*"));
+ }
+
+ @Test
+ public void testSortedSetOfMyBeanParam() {
+ final Response response = target().path("resource/myBean/sortedset")
+ .queryParam("q", "A")
+ .queryParam("q", "B")
+ .queryParam("q", "C")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*A**B**C*", str);
+ }
+
+ @Test
+ public void testStringParam() {
+ Form form = new Form();
+ form.param("form", "formParam");
+ final Response response = target()
+ .path("resource/string").path("pathParam")
+ .matrixParam("matrix", "matrixParam")
+ .queryParam("query", "queryParam")
+ .request()
+ .header("header", "headerParam")
+ .cookie("cookie", "cookieParam")
+ .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+
+ final String str = response.readEntity(String.class);
+ assertEquals("-pathParam-_-matrixParam-_-queryParam-_-headerParam-_-cookieParam-_-formParam-", str);
+ }
+
+ @Test
+ @Ignore("TODO: ParamConversion not yet implemented in the ResponseBuilder (JERSEY-1385).")
+ // TODO: JERSEY-1385: after clarifying with spec the ResponseBuilder paramconversion should be finished (or removed)
+ public void testStringParamInResponse() {
+ final Response response = target().path("resource/response").request().get();
+ assertEquals("-:res-head:-", response.getHeaderString("response-header"));
+
+ }
+
+ @Test
+ public void testMyBeanFormParamDefault() {
+ Form form = new Form();
+ Response response = target().path("resource/myBeanFormDefault")
+ .request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ String str = response.readEntity(String.class);
+ assertEquals("*form-default*", str);
+ }
+
+ @Test
+ public void testMyBeanQueryParamDefault() {
+ final Response response = target().path("resource/myBeanQueryDefault")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*query-default*", str);
+ }
+
+ @Test
+ public void testMyBeanMatrixParamDefault() {
+ final Response response = target().path("resource/myBeanMatrixDefault")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*matrix-default*", str);
+ }
+
+ @Test
+ public void testMyBeanCookieParamDefault() {
+ final Response response = target().path("resource/myBeanCookieDefault")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*cookie-default*", str);
+ }
+
+ @Test
+ public void testMyBeanHeaderParamDefault() {
+ final Response response = target().path("resource/myBeanHeaderDefault")
+ .request().get();
+ final String str = response.readEntity(String.class);
+ assertEquals("*header-default*", str);
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @POST
+ @Path("myBean/{path}")
+ public String postMyBean(@PathParam("path") MyBean pathParam, @MatrixParam("matrix") MyBean matrix,
+ @QueryParam("query") MyBean query, @HeaderParam("header") MyBean header,
+ @CookieParam("cookie") MyBean cookie, @FormParam("form") MyBean form) {
+ return pathParam.getValue() + "_" + matrix.getValue() + "_" + query.getValue() + "_" + header.getValue() + "_"
+ + cookie.getValue() + "_" + form.getValue();
+ }
+
+ @GET
+ @Path("myBean/list")
+ public String postMyBean(@QueryParam("q") List<MyBean> query) {
+ StringBuilder sb = new StringBuilder();
+ for (MyBean bean : query) {
+ sb.append(bean.getValue());
+ }
+
+ return sb.toString();
+ }
+
+ @GET
+ @Path("myBean/set")
+ public String postMyBean(@QueryParam("q") Set<MyBean> query) {
+ StringBuilder sb = new StringBuilder();
+ for (MyBean bean : query) {
+ sb.append(bean.getValue());
+ }
+
+ return sb.toString();
+ }
+
+ @GET
+ @Path("myBean/sortedset")
+ public String postMyBean(@QueryParam("q") SortedSet<MyBean> query) {
+ StringBuilder sb = new StringBuilder();
+ for (MyBean bean : query) {
+ sb.append(bean.getValue());
+ }
+
+ return sb.toString();
+ }
+
+ @POST
+ @Path("myBeanFormDefault")
+ public String postMyBeanFormDefault(@DefaultValue("form-default") @FormParam("form") MyBean pathParam) {
+ return pathParam.getValue();
+ }
+
+ @GET
+ @Path("myBeanQueryDefault")
+ public String getMyBeanQueryDefault(@DefaultValue("query-default") @QueryParam("q") MyBean queryParam) {
+ return queryParam.getValue();
+ }
+
+ @GET
+ @Path("myBeanMatrixDefault")
+ public String getMyBeanMatrixDefault(@DefaultValue("matrix-default") @MatrixParam("m") MyBean matrixParam) {
+ return matrixParam.getValue();
+ }
+
+ @GET
+ @Path("myBeanCookieDefault")
+ public String getMyBeanCookieDefault(@DefaultValue("cookie-default") @CookieParam("c") MyBean cookieParam) {
+ return cookieParam.getValue();
+ }
+
+ @GET
+ @Path("myBeanHeaderDefault")
+ public String getMyBeanHeaderDefault(@DefaultValue("header-default") @HeaderParam("h") MyBean headerParam) {
+ return headerParam.getValue();
+ }
+
+ @POST
+ @Path("string/{path}")
+ public String postString(@PathParam("path") String pathParam, @MatrixParam("matrix") String matrix,
+ @QueryParam("query") String query, @HeaderParam("header") String header,
+ @CookieParam("cookie") String cookie, @FormParam("form") String form) {
+ return pathParam + "_" + matrix + "_" + query + "_" + header + "_"
+ + cookie + "_" + form;
+ }
+
+ @GET
+ @Path("q")
+ public String get(@QueryParam("query") String query) {
+ return query;
+ }
+
+ @GET
+ @Path("response")
+ public Response getResponse() {
+ return Response.ok().header("response-header", "res-head").entity("anything").build();
+ }
+ }
+
+ public static class MyParamProvider implements ParamConverterProvider {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ if (rawType != MyBean.class) {
+ return null;
+ }
+
+ return (ParamConverter<T>) new ParamConverter<MyBean>() {
+
+ @Override
+ public MyBean fromString(String value) throws IllegalArgumentException {
+ final MyBean myBean = new MyBean();
+ myBean.setValue("*" + value + "*");
+ return myBean;
+ }
+
+ @Override
+ public String toString(MyBean bean) throws IllegalArgumentException {
+ return "*:" + bean.getValue() + ":*";
+ }
+
+ };
+ }
+ }
+
+ public static class MyStringParamProvider implements ParamConverterProvider {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ if (rawType != String.class) {
+ return null;
+ }
+
+ return (ParamConverter<T>) new ParamConverter<String>() {
+
+ @Override
+ public String fromString(String value) throws IllegalArgumentException {
+ return "-" + value + "-";
+ }
+
+ @Override
+ public String toString(String str) throws IllegalArgumentException {
+ return "-:" + str + ":-";
+ }
+
+ };
+ }
+ }
+
+ public static class MyBean implements Comparable<MyBean> {
+
+ private String value;
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "MyBean{"
+ + "value='" + value + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof MyBean)) {
+ return false;
+ }
+
+ MyBean myBean = (MyBean) o;
+
+ return !(value != null ? !value.equals(myBean.value) : myBean.value != null);
+ }
+
+ @Override
+ public int hashCode() {
+ return value != null ? value.hashCode() : 0;
+ }
+
+ @Override
+ public int compareTo(MyBean o) {
+ return value.compareTo(o.value);
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PathEncodingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PathEncodingTest.java
new file mode 100644
index 0000000..19abcc3
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PathEncodingTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing encoding of {@Path path annotations}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class PathEncodingTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(PercentEncodedTest.class, AsteriskResource.class);
+ }
+
+ @Test
+ public void test1() {
+ assertEquals("ok", target().path("test").path("[]").request().get(String.class));
+ }
+
+ @Test
+ public void test2() {
+ assertEquals("ok", target().path("test").path("%5b%5d").request().get(String.class));
+ }
+
+ @Test
+ public void test3() {
+ assertEquals("ok", target().path("test").path("%5b%5D").request().get(String.class));
+ }
+
+ @Test
+ public void testComplex1() {
+ assertEquals("a-ok", target().path("test").path("test/a/[]").request().get(String.class));
+ }
+
+ @Test
+ public void testComplex2() {
+ assertEquals("a-ok", target().path("test").path("test/a/%5b%5D").request().get(String.class));
+ }
+
+ @Test
+ public void testComplex3() {
+ final Response res = target().path("test").path("test/a/path/%5b%5d").request().get();
+ assertEquals(200, res.getStatus());
+ assertEquals("a-ok", res.readEntity(String.class));
+ }
+
+ @Test
+ public void testNotFound() {
+ final Response res = target().path("test").path("test/a/path/%5ab").request().get();
+ assertEquals(404, res.getStatus());
+ }
+
+ @Test
+ public void testComplex4() {
+ assertEquals("a-ok", target().path("test").path("test/a/path/[]").request().get(String.class));
+ }
+
+ @Test
+ public void testSlash() {
+ assertEquals("ok", target().path("test/slash/").request().get(String.class));
+ }
+
+ @Test
+ public void testWithoutSlash() {
+ assertEquals("ok", target().path("test/slash").request().get(String.class));
+ }
+
+ @Test
+ public void testAsteriskInPath() {
+ Response response = target().path("*").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("ok", response.readEntity(String.class));
+ }
+
+ @Path("*")
+ public static class AsteriskResource {
+ @GET
+ public String get() {
+ return "ok";
+ }
+ }
+
+ @Path("test")
+ public static class PercentEncodedTest {
+
+ @GET
+ @Path("[]")
+ public String simple() {
+ return "ok";
+ }
+
+ @GET
+ @Path("slash/")
+ public String slash(@Context UriInfo uri) {
+ return "ok";
+ }
+
+ @GET
+ @Path("test/{a : .* }/[]")
+ public String complex(@PathParam("a") String a) {
+ return a + "-ok";
+ }
+
+ @GET
+ @Path("test/{a : .* }/path/%5b%5D")
+ public String complex2(@PathParam("a") String a) {
+ return a + "-ok";
+ }
+
+
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PerRequestLifecycleTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PerRequestLifecycleTest.java
new file mode 100644
index 0000000..be23404
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PerRequestLifecycleTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Marc Hadley
+ */
+public class PerRequestLifecycleTest extends JerseyTest {
+
+ /**
+ * Enum representing the actual state of the resource in the lifecycle.
+ */
+ private static enum ResourceState {
+ NEW,
+ CONSTRUCTED,
+ DESTROYED
+ }
+
+ @Path("/post-construct")
+ public static class PostConstructResource {
+ private int count;
+
+ @Context
+ Configuration configuration;
+
+ public PostConstructResource() {
+ this.count = 0;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ assertNotNull(configuration);
+ count++;
+ }
+
+ @GET
+ public String doGet() {
+ return Integer.toString(count);
+ }
+ }
+
+ private static ResourceState preDestroyState = ResourceState.NEW;
+ private static CountDownLatch preDestroyCdl = new CountDownLatch(1);
+
+ @Path("pre-destroy")
+ public static class PreDestroyResource {
+ public PreDestroyResource() throws IOException {
+ preDestroyState = ResourceState.CONSTRUCTED;
+ }
+
+ @GET
+ public String getFileName() {
+ return preDestroyState.name();
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ assertEquals(ResourceState.CONSTRUCTED, preDestroyState);
+ preDestroyState = ResourceState.DESTROYED;
+ preDestroyCdl.countDown();
+ }
+ }
+
+ @Path("referred")
+ public static class ReferredToResource {
+ @Path("sub")
+ public ReferencingOfResource get() {
+ return new ReferencingOfResource();
+ }
+ }
+
+ private static ResourceState prePostState = ResourceState.NEW;
+ private static CountDownLatch prePostCdl = new CountDownLatch(1);
+
+ @Path("pre-post")
+ public static class PreDestroyPostConstructResource {
+
+ @PostConstruct
+ public void postConstruct() throws IOException {
+ prePostState = ResourceState.CONSTRUCTED;
+ }
+
+ @GET
+ public String getState() {
+ return prePostState.name();
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ assertEquals(ResourceState.CONSTRUCTED, prePostState);
+ prePostState = ResourceState.DESTROYED;
+ prePostCdl.countDown();
+ }
+ }
+
+ private static ResourceState prePostPrivateState = ResourceState.NEW;
+ private static CountDownLatch prePostPrivateCdl = new CountDownLatch(1);
+
+ @Path("pre-post-private")
+ public static class PreDestroyPostConstructResourcePrivate {
+
+ @PostConstruct
+ private void postConstruct() throws IOException {
+ prePostPrivateState = ResourceState.CONSTRUCTED;
+ }
+
+ @GET
+ public String getState() {
+ return prePostPrivateState.name();
+ }
+
+ @PreDestroy
+ private void preDestroy() {
+ assertEquals(ResourceState.CONSTRUCTED, prePostPrivateState);
+ prePostPrivateState = ResourceState.DESTROYED;
+ prePostPrivateCdl.countDown();
+ }
+ }
+
+ private static ResourceState prePostProtectedState = ResourceState.NEW;
+ private static CountDownLatch prePostProtectedCdl = new CountDownLatch(1);
+
+ @Path("pre-post-protected")
+ public static class PreDestroyPostConstructResourceProtected {
+
+ @PostConstruct
+ protected void postConstruct() throws IOException {
+ prePostProtectedState = ResourceState.CONSTRUCTED;
+ }
+
+ @GET
+ public String getState() {
+ return prePostProtectedState.name();
+ }
+
+ @PreDestroy
+ protected void preDestroy() {
+ assertEquals(ResourceState.CONSTRUCTED, prePostProtectedState);
+ prePostProtectedState = ResourceState.DESTROYED;
+ prePostProtectedCdl.countDown();
+ }
+ }
+
+ private static ResourceState inheritedState = ResourceState.NEW;
+ private static CountDownLatch inheritedCdl = new CountDownLatch(1);
+
+ public abstract static class PostConstructResourceInherited {
+ @PostConstruct
+ private void postConstruct() throws IOException {
+ inheritedState = ResourceState.CONSTRUCTED;
+ }
+
+ @GET
+ public String getState() {
+ return inheritedState.name();
+ }
+ }
+
+
+ @Path("inherited")
+ public static class PreDestroyResourceInherited extends PostConstructResourceInherited {
+
+ @PreDestroy
+ private void preDestroy() {
+ assertEquals(ResourceState.CONSTRUCTED, inheritedState);
+ inheritedState = ResourceState.DESTROYED;
+ inheritedCdl.countDown();
+ }
+ }
+
+ public static class ReferencingOfResource {
+ @GET
+ public String get(@Context final ResourceContext rc) {
+ final ReferredToResource r1 = rc.getResource(ReferredToResource.class);
+ final ReferredToResource r2 = rc.getResource(ReferredToResource.class);
+ assertEquals(r1, r2);
+ return "GET";
+ }
+ }
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(PreDestroyPostConstructResource.class, PreDestroyPostConstructResourcePrivate.class,
+ PreDestroyPostConstructResourceProtected.class, PreDestroyResourceInherited.class,
+ ReferredToResource.class, PreDestroyResource.class, PostConstructResource.class);
+ }
+
+ @Test
+ public void testPostConstructResource() {
+ final WebTarget target = target().path("post-construct");
+ assertEquals("1", target.request().get(String.class));
+ assertEquals("1", target.request().get(String.class));
+ assertEquals("1", target.request().get(String.class));
+ }
+
+ @Test
+ public void testPreDestroyResource() throws InterruptedException {
+ final String s = target().path("pre-destroy").request().get(String.class);
+ assertEquals(ResourceState.CONSTRUCTED.name(), s);
+ preDestroyCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(ResourceState.DESTROYED, preDestroyState);
+ }
+
+ @Test
+ public void testReferredToResource() {
+ assertEquals("GET", target().path("referred/sub").request().get(String.class));
+ }
+
+
+ @Test
+ public void testPreDestroyPostCreateResource() throws InterruptedException {
+ final String s = target().path("pre-post").request().get(String.class);
+ assertEquals(ResourceState.CONSTRUCTED.name(), s);
+ prePostCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(ResourceState.DESTROYED, prePostState);
+ }
+
+ @Test
+ public void testPreDestroyPostCreateResourcePrivate() throws InterruptedException {
+ final String s = target().path("pre-post-private").request().get(String.class);
+ assertEquals(ResourceState.CONSTRUCTED.name(), s);
+ prePostPrivateCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(ResourceState.DESTROYED, prePostPrivateState);
+ }
+
+ @Test
+ public void testPreDestroyPostCreateResourceProtected() throws InterruptedException {
+ final String s = target().path("pre-post-protected").request().get(String.class);
+ assertEquals(ResourceState.CONSTRUCTED.name(), s);
+ prePostProtectedCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(ResourceState.DESTROYED, prePostProtectedState);
+ }
+
+ @Test
+ public void testPreDestroyPostCreateResourceInherited() throws InterruptedException {
+ final String s = target().path("inherited").request().get(String.class);
+ assertEquals(ResourceState.CONSTRUCTED.name(), s);
+ inheritedCdl.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(ResourceState.DESTROYED, inheritedState);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PostConstructTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PostConstructTest.java
new file mode 100644
index 0000000..d3812ba
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PostConstructTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.annotation.PostConstruct;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing that {@link Context injection} is done before invoking method annotated with {@link PostConstruct}.
+ *
+ * @author Michal Gajdos
+ */
+public class PostConstructTest extends JerseyTest {
+
+ @Path("/")
+ public static class Resource {
+
+ private int value;
+
+ @Context
+ private UriInfo uri;
+
+ @Context
+ private Configuration configuration;
+
+ @PostConstruct
+ public void postConstruct() {
+ value = configuration != null ? 1 : 0;
+ }
+
+ @GET
+ public String get() {
+ return "value=" + value + "|" + configuration.getProperty("value");
+ }
+ }
+
+ public static class MyApplication extends Application {
+
+ private int value;
+
+ @Context
+ private UriInfo uriInfo;
+
+ @PostConstruct
+ public void postConstruct() {
+ value = uriInfo != null ? 1 : 0;
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.singleton(Resource.class);
+ }
+
+ @Override
+ public Map<String, Object> getProperties() {
+ final HashMap<String, Object> map = new HashMap<>();
+ map.put("value", value);
+ return map;
+ }
+ }
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ // If strategy is not IMMEDIATE then test will fail even before @Before setup method invocation.
+ // It has no other reason then just run the tests in IMMEDIATE strategy.
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ return DeploymentContext.newInstance(MyApplication.class);
+ } else {
+ return DeploymentContext.newInstance(new ResourceConfig());
+ }
+ }
+
+ @Test
+ public void testApplicationResourcePostConstruct() throws Exception {
+ assertEquals("value=1|1", target().request().get(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PrimitiveTypesTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PrimitiveTypesTest.java
new file mode 100644
index 0000000..7dabf96
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/PrimitiveTypesTest.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * Tests primitive types as entity.
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(ConcurrentRunner.class)
+public class PrimitiveTypesTest extends JerseyTest {
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testInteger() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Integer").request().post(Entity.entity(5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Integer(6), response.readEntity(Integer.class));
+ }
+
+ @Test
+ public void testPrimitiveInt() {
+ WebTarget web = target().path("test");
+ Response response = web.path("int").request().post(Entity.entity(5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Integer(6), response.readEntity(Integer.class));
+ }
+
+ @Test
+ public void testPrimitiveIntNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("int").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+
+ @Test
+ public void testLong() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Long").request().post(Entity.entity(5L, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Long(6), response.readEntity(Long.class));
+ }
+
+ @Test
+ public void testPrimitiveLong() {
+ WebTarget web = target().path("test");
+ Response response = web.path("long").request().post(Entity.entity(5L, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(6L, (long) response.readEntity(long.class));
+ }
+
+ @Test
+ public void testPrimitiveLongNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("long").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+
+ @Test
+ public void testShort() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Short").request().post(Entity.entity((short) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Short((short) 6), response.readEntity(Short.class));
+ }
+
+ @Test
+ public void testPrimitiveShort() {
+ WebTarget web = target().path("test");
+ Response response = web.path("short").request().post(Entity.entity((short) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals((short) 6, (short) response.readEntity(short.class));
+ }
+
+ @Test
+ public void testPrimitiveShortNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("short").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testByte() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Byte").request().post(Entity.entity((byte) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Byte((byte) 6), response.readEntity(Byte.class));
+ }
+
+ @Test
+ public void testPrimitiveByte() {
+ WebTarget web = target().path("test");
+ Response response = web.path("byte").request().post(Entity.entity((byte) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals((byte) 6, (byte) response.readEntity(byte.class));
+ }
+
+ @Test
+ public void testPrimitiveByteNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("byte").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testFloat() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Float").request().post(Entity.entity((float) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Float(6), response.readEntity(Float.class));
+ }
+
+ @Test
+ public void testPrimitiveFloat() {
+ WebTarget web = target().path("test");
+ Response response = web.path("float").request().post(Entity.entity(5f, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(6f, response.readEntity(float.class), 0.0f);
+ }
+
+ @Test
+ public void testPrimitiveFloatNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("float").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testDouble() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Double").request().post(Entity.entity((double) 5, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Double(6), response.readEntity(Double.class));
+ }
+
+ @Test
+ public void testPrimitiveDouble() {
+ WebTarget web = target().path("test");
+ Response response = web.path("double").request().post(Entity.entity(5d, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(6d, response.readEntity(double.class), 0.0d);
+ }
+
+ @Test
+ public void testPrimitiveDoubleNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("double").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testCharacter() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Character").request().post(Entity.entity('a', MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new Character('b'), response.readEntity(Character.class));
+ }
+
+ @Test
+ public void testPrimitiveCharacter() {
+ WebTarget web = target().path("test");
+ Response response = web.path("char").request().post(Entity.entity('a', MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals('b', (char) response.readEntity(char.class));
+ }
+
+ @Test
+ public void testPrimitiveCharacterNull() {
+ WebTarget web = target().path("test");
+ Response response = web.path("char").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testString() {
+ WebTarget web = target().path("test");
+ Response response = web.path("String").request().post(Entity.entity("String", MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals("StringPOST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testBoolean() {
+ WebTarget web = target().path("test");
+ Response response = web.path("Boolean").request().post(Entity.entity(Boolean.TRUE, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(Boolean.FALSE, response.readEntity(Boolean.class));
+ }
+
+
+ @Test
+ public void testPrimitiveBoolean() {
+ WebTarget web = target().path("test");
+ Response response = web.path("boolean").request().post(Entity.entity(true, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertFalse(response.readEntity(boolean.class));
+ }
+
+ @Test
+ public void testBigDecimal() {
+ WebTarget web = target().path("test");
+ Response response = web.path("bigDecimal").request().post(Entity.entity(new BigDecimal("15"), MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new BigDecimal("16"), response.readEntity(BigDecimal.class));
+ }
+
+ @Test
+ public void testBigInteger() {
+ WebTarget web = target().path("test");
+ Response response = web.path("bigInteger").request().post(Entity.entity(new BigInteger("15"), MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(new BigInteger("16"), response.readEntity(BigInteger.class));
+ }
+
+ @Test
+ public void testAtomicInteger() {
+ WebTarget web = target().path("test");
+ Response response = web.path("atomicInteger").request().post(Entity.entity(new AtomicInteger(15),
+ MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(16, response.readEntity(AtomicInteger.class).get());
+ }
+
+ @Test
+ public void testAtomicLong() {
+ WebTarget web = target().path("test");
+ Response response = web.path("atomicLong").request().post(Entity.entity(new AtomicLong(15),
+ MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(16, response.readEntity(AtomicLong.class).get());
+ }
+
+
+ @Path("test")
+ public static class Resource {
+ @GET
+ @Path("testik")
+ public String test(@QueryParam("id") int id) {
+ System.out.println(id);
+ return String.valueOf(id);
+ }
+
+ @POST
+ @Path("Integer")
+ public Integer postInteger(Integer i) {
+ return i + 1;
+ }
+
+ @POST
+ @Path("int")
+ public int postInt(int i) {
+ return i + 1;
+ }
+
+ @POST
+ @Path("Long")
+ public Long postLong(Long l) {
+ return l + 1;
+ }
+
+ @POST
+ @Path("long")
+ public long postLong(long l) {
+ return l + 1;
+ }
+
+ @POST
+ @Path("Short")
+ public long postShort(Short s) {
+ return s + 1;
+ }
+
+
+ @POST
+ @Path("short")
+ public long postPrimitiveShort(short s) {
+ return s + 1;
+ }
+
+
+ @POST
+ @Path("Byte")
+ public Byte postByte(Byte b) {
+ return (byte) (b + 1);
+ }
+
+ @POST
+ @Path("byte")
+ public byte postPrimitiveByte(byte b) {
+ return (byte) (b + 1);
+ }
+
+
+ @POST
+ @Path("Float")
+ public Float postFloat(Float f) {
+ return f + 1f;
+ }
+
+
+ @POST
+ @Path("float")
+ public float postPrimitiveFloat(float f) {
+ return f + 1;
+ }
+
+ @POST
+ @Path("Double")
+ public Double postDouble(Double d) {
+ return d + 1d;
+ }
+
+
+ @POST
+ @Path("double")
+ public double postPrimitiveDouble(double d) {
+ return d + 1;
+ }
+
+
+ @POST
+ @Path("Character")
+ public Character postCharacter(Character c) {
+ byte b = (byte) (c.charValue());
+ b = (byte) (b + 1);
+ return (char) b;
+ }
+
+ @POST
+ @Path("char")
+ public char postPrimitiveChar(char c) {
+ byte b = (byte) c;
+ b = (byte) (b + 1);
+ return (char) b;
+ }
+
+ @POST
+ @Path("String")
+ public String postString(String str) {
+ return str + "POST";
+ }
+
+ @POST
+ @Path("Boolean")
+ public Boolean postBoolean(Boolean b) {
+ boolean bool = b;
+ return !bool;
+ }
+
+ @POST
+ @Path("boolean")
+ public Boolean postPrimitiveBoolean(boolean b) {
+ return !b;
+ }
+
+ @Path("bigDecimal")
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public BigDecimal number(BigDecimal number) {
+ return number.add(new BigDecimal("1"));
+ }
+
+
+ @Path("bigInteger")
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public BigInteger bigInteger(BigInteger bigInteger) {
+ return bigInteger.add(new BigInteger("1"));
+ }
+
+ @Path("atomicInteger")
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public AtomicInteger atomicInteger(AtomicInteger atomic) {
+ atomic.incrementAndGet();
+ return atomic;
+ }
+
+ @Path("atomicLong")
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public AtomicLong atomicLong(AtomicLong atomic) {
+ atomic.incrementAndGet();
+ return atomic;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ReloadTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ReloadTest.java
new file mode 100644
index 0000000..c8d4f6f
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ReloadTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reload capability test.
+ *
+ * For jdk http server test container, run with:
+ *
+ * mvn -Dtest=ReloadTest -Djersey.config.test.container.factory=org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory clean test
+ *
+ * For simple test container, run with:
+ *
+ * mvn -Dtest=ReloadTest -Djersey.config.test.container.factory=org.glassfish.jersey.test.simple.SimpleTestContainerFactory clean test
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ReloadTest extends JerseyTest {
+
+ @Path("one")
+ public static class One {
+ @GET
+ public String get() {
+ return "one";
+ }
+ }
+
+ @Path("two")
+ public static class Two {
+ @GET
+ public String get() {
+ return "two";
+ }
+ }
+
+ private static class Reloader extends AbstractContainerLifecycleListener {
+ Container container;
+
+
+ public void reload(ResourceConfig rc) {
+ container.reload(rc);
+ }
+
+ @Override
+ public void onStartup(Container container) {
+ this.container = container;
+ }
+ }
+
+ ResourceConfig rc;
+ Reloader reloader;
+
+ private ResourceConfig _createRC(Reloader r) {
+ final ResourceConfig result = new ResourceConfig(One.class);
+ result.registerInstances(r);
+
+ return result;
+ }
+
+ @Override
+ public ResourceConfig configure() {
+ reloader = new Reloader();
+ return rc = _createRC(reloader);
+ }
+
+
+ @Test
+ public void testReload() {
+
+ assertEquals("one", target().path("one").request().get().readEntity(String.class));
+ assertEquals(404, target().path("two").request().get().getStatus());
+
+ rc = _createRC(reloader).registerClasses(Two.class);
+ reloader.reload(rc);
+
+ assertEquals("one", target().path("one").request().get().readEntity(String.class));
+ assertEquals("two", target().path("two").request().get().readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RequestScopedAndAsyncTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RequestScopedAndAsyncTest.java
new file mode 100644
index 0000000..30e4372
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RequestScopedAndAsyncTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JERSEY-2677 reproducer - test, that {@code Factory.dispose()} is correctly called for both sync and async cases.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class RequestScopedAndAsyncTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(RequestScopedAndAsyncTest.class.getName());
+
+ // latch to prevent, that the balance is checked before dispose() is called
+ private static CountDownLatch cdl;
+
+ public static class Injectable {
+ private String message = "Hello";
+ public String getMessage() {
+ return message;
+ }
+ }
+
+ public static class InjectableFactory implements DisposableSupplier<Injectable> {
+ private static AtomicInteger provided = new AtomicInteger(0);
+ private static AtomicInteger balance = new AtomicInteger(0);
+
+ @Override
+ public Injectable get() {
+ LOGGER.fine("Factory provide() called.");
+ provided.incrementAndGet();
+ balance.incrementAndGet();
+ return new Injectable();
+ }
+
+ @Override
+ public void dispose(Injectable i) {
+ LOGGER.fine("Factory dispose() called. ");
+ balance.decrementAndGet();
+ cdl.countDown();
+ }
+
+ public static void reset() {
+ LOGGER.fine("Factory reset() called.");
+ provided.set(0);
+ balance.set(0);
+ cdl = new CountDownLatch(1);
+ }
+
+ public static int getProvidedCount() {
+ return provided.intValue();
+ }
+
+ public static int getBalanceValue() {
+ return balance.intValue();
+ }
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @Inject
+ private Injectable injectable;
+
+ @GET
+ @Path("sync")
+ public Response sync() {
+ LOGGER.fine("Injected message: " + injectable.getMessage());
+ return Response.noContent().build();
+ }
+
+ @GET
+ @Path("async")
+ public void async(@Suspended AsyncResponse ar) {
+ LOGGER.fine("Injected message: " + injectable.getMessage());
+ ar.resume(Response.noContent().build());
+ }
+ }
+
+ @Before
+ public void resetCounters() {
+ InjectableFactory.reset();
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class)
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindFactory(InjectableFactory.class)
+ .to(Injectable.class)
+ .in(RequestScoped.class);
+ }
+ });
+ }
+
+ @Test
+ public void testInstanceReleaseAsync() throws ExecutionException, InterruptedException {
+ Future<Response> future = target("/test/async").request().async().get();
+ Response response = future.get();
+
+ assertEquals(204, response.getStatus());
+ assertEquals(1, InjectableFactory.getProvidedCount());
+ try {
+ cdl.await(500, TimeUnit.MILLISECONDS);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.INFO, "CountDownLatch interrupted: ", e);
+ }
+ assertEquals(0, InjectableFactory.getBalanceValue());
+ }
+
+ @Test
+ public void testInstanceReleaseSync() {
+ assertEquals(204, target("/test/sync").request().get().getStatus());
+ assertEquals(1, InjectableFactory.getProvidedCount());
+ assertEquals(0, InjectableFactory.getBalanceValue());
+ }
+
+ @Test
+ public void shouldProvideAndDisposeSync2() {
+ assertEquals(204, target("/test/sync").request().get().getStatus());
+ assertEquals(1, InjectableFactory.getProvidedCount());
+ assertEquals(0, InjectableFactory.getBalanceValue());
+ }
+
+ @Test
+ public void shouldProvideAndDisposeAsync2() throws ExecutionException, InterruptedException {
+ assertEquals(204, target("/test/async").request().get().getStatus());
+ assertEquals(1, InjectableFactory.getProvidedCount());
+ try {
+ cdl.await(500, TimeUnit.MILLISECONDS);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.INFO, "CountDownLatch interrupted: ", e);
+ }
+ assertEquals(0, InjectableFactory.getBalanceValue());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceConfigTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceConfigTest.java
new file mode 100644
index 0000000..f6f4f04
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceConfigTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.Formatter;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * End to end test class for testing {@code ResourceConfig} features.
+ *
+ * @author Michal Gajdos
+ */
+public class ResourceConfigTest extends JerseyTest {
+
+ @SuppressWarnings({"UnusedDeclaration", "StringEquality", "RedundantIfStatement"})
+ @XmlRootElement
+ public static class Property {
+
+ private String name;
+ private String value;
+
+ public Property() {
+ }
+
+ public Property(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Property)) {
+ return false;
+ }
+ final Property other = (Property) obj;
+ if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) {
+ return false;
+ }
+ if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = hash * 47 + (name == null ? 0 : name.hashCode());
+ hash = hash * 47 + (value == null ? 0 : value.hashCode());
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return new Formatter().format("Property(name=%s,value=%s)", name, value).toString();
+ }
+
+ }
+
+ @Path("/")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public static class Resource {
+
+ @POST
+ public Property post(final Property property) {
+ return property;
+ }
+
+ }
+
+ /**
+ * Application similar to the one that needs to register a custom {@code Feature} to run properly
+ * and is supposed to be present in WAR files.
+ */
+ public static class Jersey1094 extends ResourceConfig {
+
+ public Jersey1094() {
+ registerClasses(Resource.class, JettisonFeature.class);
+ }
+
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ // Simulate the creation of the ResourceConfig as if it was created during servlet initialization
+ return ResourceConfig.forApplicationClass(Jersey1094.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(new JettisonFeature());
+ }
+
+ /**
+ * Tests whether the {@code ApplicationHandler} is able to register and use custom binders provided by an extension of
+ * {@code ResourceConfig} if only a class reference of this extension is passed in the {@code ResourceConfig} to the
+ * {@code ApplicationHandler}.
+ * <p/>
+ * Test is trying to simulate the behaviour of Jersey as if the application was deployed into a servlet container
+ * with a servlet defined in {@code web.xml} file using {@code init-param} {@code javax.ws.rs.Application}.
+ */
+ @Test
+ public void testJersey1094() throws Exception {
+ Property testInstance = new Property("myProp", "myVal");
+
+ final Property returnedValue = target()
+ .path("/")
+ .request("application/json")
+ .post(Entity.entity(testInstance, "application/json"), Property.class);
+
+ assertEquals(testInstance, returnedValue);
+ }
+
+ @Test
+ @Ignore("TODO: Add test for reloading resource config in the container (once it is supported)")
+ public void testJersey1094ReloadResourceConfig() throws Exception {
+ // TODO test reloading resource config in the container (once it is supported)
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceFilterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceFilterTest.java
new file mode 100644
index 0000000..7cb4a45
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceFilterTest.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.Principal;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NameBinding;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * JAX-RS name-bound filter tests.
+ *
+ * @author Martin Matula
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @author Miroslav.Fuksa
+ * @see GloballyNameBoundResourceFilterTest
+ */
+public class ResourceFilterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ MyDynamicFeature.class,
+ BasicTestsResource.class,
+ NameBoundRequestFilter.class,
+ NameBoundResponseFilter.class,
+ PostMatchingFilter.class,
+ // exception tests
+ ExceptionTestsResource.class,
+ ExceptionPreMatchRequestFilter.class,
+ ExceptionPostMatchRequestFilter.class,
+ ExceptionTestBoundResponseFilter.class,
+ ExceptionTestGlobalResponseFilter.class,
+ TestExceptionMapper.class,
+ AbortResponseResource.class,
+ AbortResponseFitler.class,
+ AbortRequestFilter.class,
+ ExceptionRequestFilter.class
+ );
+ }
+
+ @Test
+ public void testDynamicBinder() {
+ test("dynamicBinder");
+ }
+
+ @Test
+ public void testNameBoundRequest() {
+ test("nameBoundRequest");
+ }
+
+ @Test
+ public void testNameBoundResponse() {
+ test("nameBoundResponse");
+ }
+
+ @Test
+ public void testPostMatching() {
+ test("postMatching");
+ }
+
+ // See JERSEY-1554
+ @Test
+ public void testGlobalPostMatchingNotInvokedOn404() {
+ Response r = target("basic").path("not-found").request().get();
+ assertEquals(404, r.getStatus());
+ if (r.hasEntity()) {
+ assertThat(r.readEntity(String.class), not(containsString("postMatching")));
+ }
+ }
+
+ private void test(String name) {
+ Response r = target("basic").path(name).request().get();
+ assertEquals("Unexpected HTTP response status code.", 200, r.getStatus());
+ assertTrue("Response does not have entity.", r.hasEntity());
+ assertEquals("Unexpected response entity value.", name, r.readEntity(String.class));
+ }
+
+ @Path("/basic")
+ public static class BasicTestsResource {
+
+ @Path("dynamicBinder")
+ @GET
+ public String getDynamicBinder() {
+ return "";
+ }
+
+ @Path("nameBoundRequest")
+ @GET
+ @NameBoundRequest
+ public String getNameBoundRequest() {
+ return "";
+ }
+
+ @Path("nameBoundResponse")
+ @GET
+ @NameBoundResponse
+ public String getNameBoundResponse() {
+ return "";
+ }
+
+ @Path("postMatching")
+ @GET
+ public String getPostMatching() {
+ return "";
+ }
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundRequest {}
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundAbortResponse {}
+
+ @NameBoundRequest
+ @Priority(1)
+ public static class NameBoundRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok("nameBoundRequest", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ @NameBoundResponse
+ public static class NameBoundResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ responseContext.setEntity("nameBoundResponse", responseContext.getEntityAnnotations(), MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+
+ public static class PostMatchingFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.getUriInfo().getPath().startsWith("basic")) {
+ requestContext.abortWith(Response.ok("postMatching", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+ }
+
+ @Priority(1)
+ @PreMatching
+ private static class DbFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok("dynamicBinder", MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ public static class MyDynamicFeature implements DynamicFeature {
+
+ private final DbFilter filter = new DbFilter();
+
+ @Override
+ public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
+ if ("getDynamicBinder".equals(resourceInfo.getResourceMethod().getName())) {
+ context.register(filter);
+ }
+ }
+ }
+
+ @Path("/exception")
+ public static class ExceptionTestsResource {
+
+ @Path("matched")
+ @GET
+ @ExceptionTestBound
+ public String getPostMatching() {
+ return "method";
+ }
+ }
+
+ @PreMatching
+ public static class ExceptionPreMatchRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if ("exception/not-found".equals(requestContext.getUriInfo().getPath())) {
+ throw new TestException("globalRequest");
+ }
+ }
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface ExceptionTestBound {}
+
+ @ExceptionTestBound
+ public static class ExceptionPostMatchRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ throw new TestException("nameBoundRequest");
+ }
+ }
+
+ @ExceptionTestBound
+ @Priority(10)
+ public static class ExceptionTestBoundResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ responseContext.setEntity(
+ (responseContext.hasEntity()) ? responseContext.getEntity() + "-nameBoundResponse" : "nameBoundResponse",
+ responseContext.getEntityAnnotations(),
+ MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+
+ @Priority(1)
+ public static class ExceptionTestGlobalResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ if (!requestContext.getUriInfo().getPath().startsWith("exception")) {
+ return;
+ }
+
+ responseContext.setEntity(
+ (responseContext.hasEntity()) ? responseContext.getEntity() + "-globalResponse" : "globalResponse",
+ responseContext.getEntityAnnotations(),
+ MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+
+ public static class TestException extends RuntimeException {
+
+ public TestException(String message) {
+ super(message);
+ }
+ }
+
+ public static class TestExceptionMapper implements ExceptionMapper<TestException> {
+
+ public static final String POSTFIX = "-mappedTestException";
+
+ @Override
+ public Response toResponse(TestException exception) {
+ return Response.ok(exception.getMessage() + POSTFIX).build();
+ }
+ }
+
+ @Test
+ public void testNameBoundResponseFilterNotInvokedOnPreMatchFilterException() {
+ Response r = target("exception").path("not-found").request().get();
+ assertEquals(200, r.getStatus());
+ assertTrue(r.hasEntity());
+ assertEquals("globalRequest-mappedTestException-globalResponse", r.readEntity(String.class));
+ }
+
+ @Test
+ public void testNameBoundResponseFilterInvokedOnPostMatchFilterException() {
+ Response r = target("exception").path("matched").request().get();
+ assertEquals(200, r.getStatus());
+ assertTrue(r.hasEntity());
+ assertEquals("nameBoundRequest-mappedTestException-nameBoundResponse-globalResponse", r.readEntity(String.class));
+ }
+
+ @NameBoundAbortResponse
+ private static class AbortResponseFitler implements ContainerResponseFilter {
+
+ public static final String ABORT_FILTER_TEST_PASSED = "abort-filter-test-passed";
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ boolean passed = true;
+
+ try {
+ // checks that IllegalStateException is thrown when setting entity stream
+ requestContext.setEntityStream(new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return -1;
+ }
+ });
+ passed = false;
+ } catch (IllegalStateException iae) {
+ System.out.println(iae.getMessage());
+ }
+
+ try {
+ // checks that IllegalStateException is thrown when setting security context
+ requestContext.setSecurityContext(new SecurityContext() {
+ @Override
+ public Principal getUserPrincipal() {
+ return null;
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ return false;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ return null;
+ }
+ });
+ passed = false;
+ } catch (IllegalStateException iae) {
+ System.out.println(iae.getMessage());
+ }
+
+ try {
+ // checks that IllegalStateException is thrown when aborting request
+ requestContext.abortWith(Response.serverError().build());
+ passed = false;
+ } catch (IllegalStateException iae) {
+ System.out.println(iae.getMessage());
+ }
+ responseContext.getHeaders().add(ABORT_FILTER_TEST_PASSED, passed);
+ }
+ }
+
+ @NameBoundAbortRequest
+ private static class AbortRequestFilter implements ContainerRequestFilter {
+
+ public static final String FILTER_ABORT_ENTITY = "filter-abort-entity";
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok(FILTER_ABORT_ENTITY).build());
+ }
+ }
+
+ @NameBoundExceptionInRequest
+ private static class ExceptionRequestFilter implements ContainerRequestFilter {
+
+ public static final String EXCEPTION_IN_REQUEST_FILTER = "exception-in-request-filter";
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ throw new TestException(EXCEPTION_IN_REQUEST_FILTER);
+ }
+ }
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundResponse {}
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundAbortRequest {}
+
+ @NameBinding
+ @Retention(RetentionPolicy.RUNTIME)
+ private static @interface NameBoundExceptionInRequest {}
+
+ @Path("abort")
+ public static class AbortResponseResource {
+
+ @Path("response")
+ @GET
+ @NameBoundAbortResponse
+ public String get() {
+ return "get";
+ }
+
+ @Path("abort-in-filter")
+ @GET
+ @NameBoundAbortResponse
+ @NameBoundAbortRequest
+ public String neverCalled() {
+ return "This method will never be called. Request will be aborted in a request filter.";
+ }
+
+ @Path("exception")
+ @GET
+ @NameBoundAbortResponse
+ @NameBoundExceptionInRequest
+ public String exception() {
+ return "This method will never be called. Exception will be thrown in a request filter.";
+ }
+ }
+
+ @Test
+ public void testAbortResponseInResponseFilter() {
+ Response r = target("abort").path("response").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("get", r.readEntity(String.class));
+ assertNotNull(r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ assertEquals("true", r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ }
+
+ @Test
+ public void testAbortAbortedResponseInResponseFilter() {
+ Response r = target("abort").path("abort-in-filter").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals(AbortRequestFilter.FILTER_ABORT_ENTITY, r.readEntity(String.class));
+ assertNotNull(r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ assertEquals("true", r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ }
+
+ @Test
+ public void testAbortedResponseFromExceptionResponse() {
+ Response r = target("abort").path("exception").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals(ExceptionRequestFilter.EXCEPTION_IN_REQUEST_FILTER + TestExceptionMapper.POSTFIX,
+ r.readEntity(String.class));
+ assertNotNull(r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ assertEquals("true", r.getHeaderString(AbortResponseFitler.ABORT_FILTER_TEST_PASSED));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceRoutingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceRoutingTest.java
new file mode 100644
index 0000000..6274c4a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResourceRoutingTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class ResourceRoutingTest extends JerseyTest {
+
+ @Path("a")
+ public static class ResourceA {
+ @Path("b/d")
+ @GET
+ public String get() {
+ // this method cannot be chosen as the request path "a/b/..." always firstly choose the ResourceAB and routing
+ // will never check this resource. This is based on the algorithm from the jax-rs spec 2
+ return "a/b/d";
+ }
+
+ @Path("q")
+ @GET
+ public String getQ() {
+ return "a/q";
+ }
+
+ }
+
+ @Path("a/b")
+ public static class ResourceAB {
+ @Path("c")
+ @GET
+ public String get() {
+ return "a/b/c";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResourceA.class, ResourceAB.class);
+ }
+
+
+ @Test
+ public void subWrongPath() throws Exception {
+ Response response = target("a/b/d").request().get();
+ Assert.assertEquals(404, response.getStatus());
+ }
+
+ @Test
+ public void correctPath() throws Exception {
+ Response response = target("a/b/c").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("a/b/c", response.readEntity(String.class));
+ }
+
+ @Test
+ public void correctPath2() throws Exception {
+ Response response = target("a/q").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("a/q", response.readEntity(String.class));
+ }
+
+}
+
+
+
+
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResponseStatusTypeTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResponseStatusTypeTest.java
new file mode 100644
index 0000000..7c59ae8
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ResponseStatusTypeTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Tests custom response status reason phrase with jersey containers and connectors.
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ResponseStatusTypeTest.InMemoryTest.class,
+ ResponseStatusTypeTest.GrizzlyContainerGrizzlyConnectorTest.class,
+ ResponseStatusTypeTest.GrizzlyContainerApacheConnectorTest.class,
+ ResponseStatusTypeTest.SimpleContainerHttpUrlConnectorTest.class})
+public class ResponseStatusTypeTest {
+
+ public static final String REASON_PHRASE = "my-phrase";
+
+ public static class InMemoryTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new InMemoryTestContainerFactory();
+ }
+
+ @Test
+ public void testCustom() {
+ _testCustom(target());
+ }
+
+ @Test
+ public void testBadRequest() {
+ _testBadRequest(target());
+ }
+
+ @Test
+ public void testCustomBadRequest() {
+ // with InMemory container and connector status info should be transferred as it is produced.
+ final Response response = target().path("resource/custom-bad-request").request().get();
+ Assert.assertEquals(400, response.getStatus());
+ Assert.assertNull(response.getStatusInfo().getReasonPhrase());
+
+ }
+
+ }
+
+ public static class GrizzlyContainerGrizzlyConnectorTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(new GrizzlyConnectorProvider());
+ }
+
+
+ @Test
+ public void testCustom() {
+ _testCustom(target());
+ }
+
+ @Test
+ public void testBadRequest() {
+ _testBadRequest(target());
+ }
+
+ @Test
+ public void testCustomBadRequest() {
+ _testCustomBadRequest(target());
+ }
+ }
+
+ public static class GrizzlyContainerApacheConnectorTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(new ApacheConnectorProvider());
+ }
+
+
+ @Test
+ public void testCustom() {
+ _testCustom(target());
+ }
+
+ @Test
+ public void testBadRequest() {
+ _testBadRequest(target());
+ }
+
+ @Test
+ public void testCustomBadRequest() {
+ _testCustomBadRequest(target());
+ }
+ }
+
+ public static class SimpleContainerHttpUrlConnectorTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new SimpleTestContainerFactory();
+ }
+
+ @Test
+ public void testCustom() {
+ _testCustom(target());
+ }
+
+ @Test
+ public void testBadRequest() {
+ _testBadRequest(target());
+ }
+
+ @Test
+ public void testCustomBadRequest() {
+ _testCustomBadRequest(target());
+ }
+ }
+
+ public static class JdkHttpContainerHttpUrlConnectorTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JdkHttpServerTestContainerFactory();
+ }
+
+ @Test
+ @Ignore("Jdk http container does not support custom response reason phrases.")
+ public void testCustom() {
+ _testCustom(target());
+ }
+
+ @Test
+ public void testBadRequest() {
+ _testBadRequest(target());
+ }
+
+ @Test
+ public void testCustomBadRequest() {
+ _testCustomBadRequest(target());
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @GET
+ @Path("custom")
+ public Response testStatusType() {
+ return Response.status(new Custom428Type()).build();
+ }
+
+ @GET
+ @Path("bad-request")
+ public Response badRequest() {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+
+ @GET
+ @Path("custom-bad-request")
+ public Response customBadRequest() {
+ return Response.status(new CustomBadRequestWithoutReasonType()).build();
+ }
+
+ }
+
+ public static class Custom428Type implements Response.StatusType {
+ @Override
+ public int getStatusCode() {
+ return 428;
+ }
+
+ @Override
+ public String getReasonPhrase() {
+ return REASON_PHRASE;
+ }
+
+ @Override
+ public Response.Status.Family getFamily() {
+ return Response.Status.Family.CLIENT_ERROR;
+ }
+ }
+
+ public static class CustomBadRequestWithoutReasonType implements Response.StatusType {
+ @Override
+ public int getStatusCode() {
+ return 400;
+ }
+
+ @Override
+ public String getReasonPhrase() {
+ return null;
+ }
+
+ @Override
+ public Response.Status.Family getFamily() {
+ return Response.Status.Family.CLIENT_ERROR;
+ }
+ }
+
+ public static void _testCustom(WebTarget target) {
+ final Response response = target.path("resource/custom").request().get();
+ Assert.assertEquals(428, response.getStatus());
+ Assert.assertEquals(REASON_PHRASE, response.getStatusInfo().getReasonPhrase());
+ }
+
+ public static void _testBadRequest(WebTarget target) {
+ final Response response = target.path("resource/bad-request").request().get();
+ Assert.assertEquals(400, response.getStatus());
+ Assert.assertEquals(Response.Status.BAD_REQUEST.getReasonPhrase(), response.getStatusInfo().getReasonPhrase());
+ }
+
+ public static void _testCustomBadRequest(WebTarget target) {
+ final Response response = target.path("resource/custom-bad-request").request().get();
+ Assert.assertEquals(400, response.getStatus());
+ Assert.assertEquals(Response.Status.BAD_REQUEST.getReasonPhrase(), response.getStatusInfo().getReasonPhrase());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RuntimeConfigTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RuntimeConfigTest.java
new file mode 100644
index 0000000..91e0d1b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/RuntimeConfigTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.internal.InternalProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class RuntimeConfigTest extends JerseyTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+ }
+
+ public static class EmptyFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ return true;
+ }
+ }
+
+ public static class ClientFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(ClientReaderInterceptor.class);
+ context.property("foo", "bar");
+ return true;
+ }
+ }
+
+ public static class ClientReaderInterceptor implements ReaderInterceptor {
+
+ private final Configuration config;
+
+ @Inject
+ public ClientReaderInterceptor(final Configuration configuration) {
+ this.config = configuration;
+ }
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ assertTrue(config.isRegistered(ClientFeature.class));
+ assertTrue(config.isRegistered(ClientReaderInterceptor.class));
+
+ assertThat(config.getProperties().size(), is(2));
+ assertThat(config.getProperty("foo").toString(), is("bar"));
+
+ // JsonFeature
+ assertThat(config.getProperty(InternalProperties.JSON_FEATURE_CLIENT), notNullValue());
+
+ // MetaInfAutoDiscoverable
+ assertThat(config.getInstances().size(), is(1));
+ assertTrue(config.isEnabled(ClientFeature.class));
+
+ context.getHeaders().add("CustomHeader", "ClientReaderInterceptor");
+
+ return context.proceed();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testRuntimeClientConfig() throws Exception {
+ final WebTarget target = target();
+
+ target.register(ClientFeature.class);
+
+ final Response response = target.request(MediaType.WILDCARD_TYPE).get(Response.class);
+
+ assertEquals(1, target.getConfiguration().getClasses().size());
+ assertTrue(target.getConfiguration().isRegistered(ClientFeature.class));
+ assertTrue(target.getConfiguration().getInstances().isEmpty());
+ assertTrue(target.getConfiguration().getProperties().isEmpty());
+ assertFalse(target.getConfiguration().isEnabled(ClientFeature.class));
+
+ WebTarget t = target();
+ assertEquals(0, t.getConfiguration().getClasses().size());
+ assertFalse(t.getConfiguration().isRegistered(ClientFeature.class));
+ assertTrue(t.getConfiguration().getInstances().isEmpty());
+ assertTrue(t.getConfiguration().getProperties().isEmpty());
+ assertFalse(t.getConfiguration().isEnabled(ClientFeature.class));
+
+ assertEquals("get", response.readEntity(String.class));
+ assertEquals("ClientReaderInterceptor", response.getHeaderString("CustomHeader"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SecurityContextFilterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SecurityContextFilterTest.java
new file mode 100644
index 0000000..afc7d2d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SecurityContextFilterTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.security.Principal;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * End to end test class for testing security context in the Filter and
+ * resource.
+ *
+ * @author Miroslav Fuksa
+ */
+public class SecurityContextFilterTest extends JerseyTest {
+
+ private static final String PRINCIPAL_NAME = "test_principal_setByFilter";
+ private static final String SKIP_FILTER = "skipFilter";
+ private static final String PRINCIPAL_IS_NULL = "principalIsNull";
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(SecurityContextFilter.class, Resource.class);
+ }
+
+ /**
+ * Test security context container request filter.
+ */
+ @PreMatching
+ public static class SecurityContextFilter implements ContainerRequestFilter {
+
+ // TODO: won't work until we have proxiable scope
+// @Context
+// SecurityContext securityContext;
+
+ @Override
+ public void filter(ContainerRequestContext context) {
+ Assert.assertNotNull(context.getSecurityContext());
+
+ // test injections
+ // TODO: won't work until SecurityContext is proxiable
+// Assert.assertEquals(context.getSecurityContext(), securityContext);
+
+ String header = context.getHeaders().getFirst(SKIP_FILTER);
+ if ("true".equals(header)) {
+ return;
+ }
+
+ context.setSecurityContext(new SecurityContext() {
+ @Override
+ public boolean isUserInRole(String role) {
+ return false;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return new Principal() {
+
+ @Override
+ public String getName() {
+ return PRINCIPAL_NAME;
+ }
+ };
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ return null;
+ }
+ });
+ }
+ }
+
+ /**
+ * Tests SecurityContext in filter.
+ *
+ * @throws Exception Thrown when request processing fails in the
+ * application.
+ */
+ @Test
+ public void testSecurityContextFilter() throws Exception {
+ Response response = target().path("test").request().get();
+ assertEquals(200, response.getStatus());
+ String entity = response.readEntity(String.class);
+ assertEquals(PRINCIPAL_NAME, entity);
+ }
+
+ /**
+ * Tests SecurityContext in filter.
+ *
+ * @throws Exception Thrown when request processing fails in the
+ * application.
+ */
+ @Test
+ public void testContainerSecurityContext() throws Exception {
+ Response response = target().path("test").request().header(SKIP_FILTER, "true").get();
+ assertEquals(200, response.getStatus());
+ String entity = response.readEntity(String.class);
+ Assert.assertTrue(!entity.equals(PRINCIPAL_NAME));
+ }
+
+ /**
+ * Test resource class.
+ */
+ @Path("test")
+ public static class Resource {
+
+ /**
+ * Test resource method.
+ *
+ * @param crc container request context.
+ * @return String response with principal name.
+ */
+
+ // TODO: inject SecurityContext directly once JERSEY-1282 is fixed
+ @GET
+ public String getPrincipal(@Context ContainerRequestContext crc) {
+ Assert.assertNotNull(crc.getSecurityContext());
+ Principal userPrincipal = crc.getSecurityContext().getUserPrincipal();
+ return userPrincipal == null ? PRINCIPAL_IS_NULL : userPrincipal.getName();
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ServerDestroyTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ServerDestroyTest.java
new file mode 100644
index 0000000..f2a76de
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ServerDestroyTest.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that pre destroy method on application, resources and providers is invoked.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+public class ServerDestroyTest extends JerseyTest {
+
+ private static final Map<String, Boolean> destroyed = new HashMap<>();
+
+ private Reloader reloader;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ destroyed.clear();
+ destroyed.put("application", false);
+ destroyed.put("singleton-resource", false);
+ destroyed.put("filter", false);
+ destroyed.put("writer", false);
+ destroyed.put("singleton-factory", false);
+ destroyed.put("feature", false);
+
+ super.setUp();
+ }
+
+ @Path("/")
+ @Singleton
+ public static class Resource {
+
+ @GET
+ public String get() {
+ return "resource";
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("singleton-resource", true);
+ }
+ }
+
+ public static class MyFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext,
+ final ContainerResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().putSingle("foo", "bar");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("filter", true);
+ }
+ }
+
+ public static class MyWriter implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity("writer-" + context.getEntity());
+ context.proceed();
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("writer", true);
+ }
+ }
+
+ public static class MyApplication extends Application {
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("application", true);
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Arrays.asList(
+ Resource.class,
+ MyFilter.class,
+ MyWriter.class,
+ MyContainerLifecycleListener.class,
+ MyFeature.class).stream().collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<Object> getSingletons() {
+ return Collections.singleton(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindFactory(SingletonFactory.class)
+ .to(SingletonInstance.class)
+ .in(Singleton.class);
+ }
+ });
+ }
+ }
+
+ public static class SingletonInstance {
+
+ public void dispose() {
+ destroyed.put("singleton-factory", true);
+ }
+ }
+
+ public static class SingletonFactory implements DisposableSupplier<SingletonInstance> {
+
+ @Override
+ public SingletonInstance get() {
+ return new SingletonInstance();
+ }
+
+ @Override
+ public void dispose(final SingletonInstance instance) {
+ instance.dispose();
+ }
+ }
+
+ private static class Reloader extends AbstractContainerLifecycleListener {
+
+ Container container;
+
+ public void reload(final ResourceConfig config) {
+ container.reload(config);
+ }
+
+ @Override
+ public void onStartup(final Container container) {
+ this.container = container;
+ }
+ }
+
+ public static class MyContainerLifecycleListener extends AbstractContainerLifecycleListener {
+
+ @Inject
+ private SingletonInstance instance;
+
+ @Override
+ public void onShutdown(final Container container) {
+ assertThat(instance, notNullValue());
+ }
+ }
+
+ public static class MyFeature implements Feature {
+
+ @PreDestroy
+ public void preDestroy() {
+ destroyed.put("feature", true);
+ }
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ return true;
+ }
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ reloader = new Reloader();
+
+ return DeploymentContext.newInstance(ResourceConfig.forApplicationClass(MyApplication.class).register(reloader));
+ }
+
+ @Test
+ public void testApplicationResource() throws Exception {
+ final Response response = target().request().get();
+ assertThat(response.readEntity(String.class), is("writer-resource"));
+ assertThat(response.getStringHeaders().getFirst("foo"), is("bar"));
+
+ checkDestroyed(false);
+ reloader.reload(new ResourceConfig(Resource.class));
+ checkDestroyed(true);
+ }
+
+ private void checkDestroyed(final boolean shouldBeDestroyed) {
+ for (final Map.Entry<String, Boolean> entry : destroyed.entrySet()) {
+ assertThat(entry.getKey() + " should" + (shouldBeDestroyed ? "" : " not") + " be destroyed",
+ entry.getValue(), is(shouldBeDestroyed));
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProviderTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProviderTest.java
new file mode 100644
index 0000000..16ee4a1
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProviderTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.spi.ContextResolvers;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Class testing that providers are managed correctly in the singleton scope.
+ *
+ * @author Miroslav Fuksa
+ */
+public class SingletonProviderTest extends JerseyTest {
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(SingletonResource.class, AnyFilter.class,
+ ExceptionMappingProvider.class, SingletonStringMessageProvider.class, MyContextResolver.class);
+ }
+
+ @Test
+ public void filterTest() {
+ // NOTE: Explicit acceptedMedia type definition is not needed for HttpUrlConnector, as it sends several "default" types
+ // when not set directly. For (some) other connectors (namely JdkConnector), this is required, as the inferred accepted
+ // media type is */*, which would match the provider, that produces text/test, which is what we don't want in this case.
+ String str;
+ str = target().path("resource/filter").request("text/plain").get().readEntity(String.class);
+ assertEquals("filter:1", str);
+
+ str = target().path("resource/filter").request("text/plain").get().readEntity(String.class);
+ assertEquals("filter:2", str);
+ }
+
+
+ @Test
+ public void exceptionMapperTest() {
+ // NOTE: Explicit acceptedMedia type definition is not needed for HttpUrlConnector, as it sends several "default" types
+ // when not set directly. For (some) other connectors (namely JdkConnector), this is required, as the inferred accepted
+ // media type is */*, which would match the provider, that produces text/test, which is what we don't want in this case.
+ String str;
+ str = target().path("resource/exception").request("text/plain").get().readEntity(String.class);
+ assertEquals("mapper:1", str);
+ str = target().path("resource/exception").request("text/plain").get().readEntity(String.class);
+ assertEquals("mapper:2", str);
+
+ }
+
+ @Test
+ public void messageBodyWriterTest() {
+ String str1;
+ str1 = target().path("resource/messagebody").request("text/test").get().readEntity(String.class);
+ assertTrue(str1.endsWith(":1"));
+ String str2;
+ str2 = target().path("resource/messagebody").request("text/test").get().readEntity(String.class);
+ assertTrue(str2.endsWith(":2"));
+
+ assertEquals(str1.substring(0, str1.length() - 2), str2.substring(0, str2.length() - 2));
+ }
+
+ @Test
+ public void messageBodyReaderTest() {
+ String str1 = target().path("resource/messagebodyreader").request("text/plain")
+ .put(Entity.entity("from-client", "text/test")).readEntity(String.class);
+ assertTrue(str1.endsWith(":1"));
+ String str2 = target().path("resource/messagebodyreader").request("text/plain").put(Entity.entity("from-client",
+ "text/test")).readEntity(String.class);
+ assertTrue(str2.endsWith(":2"));
+
+ assertEquals(str1.substring(0, str1.length() - 2), str2.substring(0, str2.length() - 2));
+ }
+
+ @Test
+ public void contextResolverTest() {
+ String str1 = target().path("resource/context").request("text/plain").get().readEntity(String.class);
+ assertEquals("context:1", str1);
+
+ String str2 = target().path("resource/context").request("text/plain").get().readEntity(String.class);
+ assertEquals("context:2", str2);
+ }
+
+ @Path("resource")
+ public static class SingletonResource {
+ @GET
+ @Path("filter")
+ public String getCounterFromFilter(@HeaderParam("counter") int counter) {
+ return "filter:" + counter;
+ }
+
+ @GET
+ @Path("exception")
+ public String throwException() {
+ throw new SingletonTestException("test exception");
+ }
+
+ @GET
+ @Path("messagebody")
+ @Produces("text/test")
+ public String messageBodyTest() {
+ return "messagebody:";
+ }
+
+ @PUT
+ @Path("messagebodyreader")
+ @Produces("text/plain")
+ @Consumes("text/test")
+ public String messageBodyReaderTest(String entity) {
+ return "put:" + entity;
+ }
+
+ @GET
+ @Path("context")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String testContextResolver(@Context ContextResolvers resolvers) {
+ ContextResolver<String> contextResolver = resolvers.resolve(String.class, MediaType.TEXT_PLAIN_TYPE);
+ String context = contextResolver.getContext(String.class);
+ return context;
+ }
+ }
+
+
+ public static class AnyFilter implements ContainerRequestFilter {
+ private int counter = 1;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().add("counter", String.valueOf(counter++));
+ }
+ }
+
+
+ @Provider
+ public static class ExceptionMappingProvider implements ExceptionMapper<SingletonTestException> {
+ private int counter = 1;
+
+ @Override
+ public Response toResponse(SingletonTestException exception) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("mapper:" + counter++).build();
+ }
+ }
+
+ public static class SingletonTestException extends RuntimeException {
+ public SingletonTestException() {
+ super();
+ }
+
+ public SingletonTestException(String message) {
+ super(message);
+ }
+ }
+
+ @Produces(MediaType.TEXT_PLAIN)
+ public static class MyContextResolver implements ContextResolver<String> {
+ private int i = 1;
+
+ @Override
+ public String getContext(Class<?> type) {
+ if (type == String.class) {
+ return "context:" + i++;
+ }
+ return null;
+ }
+ }
+
+ @Produces({"text/test"})
+ @Consumes({"text/test"})
+ public static final class SingletonStringMessageProvider extends AbstractMessageReaderWriterProvider<String> {
+ private int counter = 1;
+ private int readerCounter = 1;
+
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(
+ Class<String> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ return readFromAsString(entityStream, mediaType) + this + ":" + readerCounter++;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(
+ String t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ writeToAsString(t + this + ":" + counter++, entityStream, mediaType);
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProvidersResourcesTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProvidersResourcesTest.java
new file mode 100644
index 0000000..19a6f8d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonProvidersResourcesTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.internal.inject.PerLookup;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test resources which also acts as providers.
+ *
+ * @author Miroslav Fuksa
+ */
+public class SingletonProvidersResourcesTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(ResourceSingleton.class, ResourceNotSingleton.class);
+
+ final Resource.Builder resourceBuilder = Resource.builder();
+ resourceBuilder.name("programmatic").path("programmatic").addMethod("GET")
+ .handledBy(ResourceProgrammaticNotSingleton.class);
+ resourceConfig.registerResources(resourceBuilder.build());
+
+ return resourceConfig;
+ }
+
+ @Test
+ public void testResourceAsFilter() {
+ String str = target().path("singleton").request().header("singleton", "singleton").get(String.class);
+ assertTrue(str, str.startsWith("true/"));
+ String str2 = target().path("singleton").request().header("singleton", "singleton").get(String.class);
+ assertTrue(str2, str2.startsWith("true/"));
+ assertEquals(str, str2);
+ }
+
+ @Test
+ public void testResourceAsFilterAnnotatedPerLookup() {
+ String str = target().path("perlookup").request().header("not-singleton", "not-singleton").get(String.class);
+ assertTrue(str.startsWith("false/"));
+ String str2 = target().path("perlookup").request().header("not-singleton", "not-singleton").get(String.class);
+ assertTrue(str2.startsWith("false/"));
+ assertNotSame(str, str2);
+ }
+
+ @Test
+ public void testResourceProgrammatic() {
+ String str = target().path("programmatic").request().header("programmatic", "programmatic").get(String.class);
+ assertTrue(str.startsWith("false/"));
+ String str2 = target().path("programmatic").request().header("programmatic", "programmatic").get(String.class);
+ assertTrue(str2.startsWith("false/"));
+ assertNotSame(str, str2);
+ }
+
+ // this should be singleton, it means the same instance for the usage as a filter and as an resource
+ @Path("singleton")
+ public static class ResourceSingleton implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.getHeaders().containsKey("singleton")) {
+ requestContext.getHeaders().add("filter-class", this.toString());
+ }
+ }
+
+ @GET
+ public String get(@HeaderParam("filter-class") String filterClass) {
+ return String.valueOf(String.valueOf(this.toString().equals(filterClass)) + "/" + this.toString() + ":"
+ + filterClass);
+ }
+ }
+
+ // this should NOT be singleton, because it is annotated as per lookup
+ @Path("perlookup")
+ @PerLookup
+ public static class ResourceNotSingleton implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.getHeaders().containsKey("not-singleton")) {
+ requestContext.getHeaders().add("filter-class", this.toString());
+ }
+ }
+
+ @GET
+ public String get(@HeaderParam("filter-class") String filterClass) {
+ return String.valueOf(String.valueOf(this.toString().equals(filterClass)) + "/" + this.toString() + ":"
+ + filterClass);
+ }
+ }
+
+ // should not be a singleton as this is only programmatic resource and is not registered as provider
+ public static class ResourceProgrammaticNotSingleton implements ContainerRequestFilter,
+ Inflector<Request, Response> {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.getHeaders().containsKey("programmatic")) {
+ requestContext.getHeaders().add("filter-class", this.toString());
+ }
+ }
+
+ @Override //JerseyContainerRequestContext
+ public Response apply(Request request) {
+ String filterClass = ((ContainerRequestContext) request).getHeaders().getFirst("filter-class");
+ return Response.ok(String.valueOf(String.valueOf(this.toString().equals(filterClass)) + "/" + this.toString() + ":"
+ + filterClass)).build();
+ }
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonResourceTest.java
new file mode 100644
index 0000000..1073e09
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SingletonResourceTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.PerLookup;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Class testing Resources managed as singletons.
+ *
+ * @author Miroslav Fuksa
+ */
+public class SingletonResourceTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(
+ SingletonResource.class,
+ ChildInheritsParentAnnotation.class,
+ ChildImplementsInterfaceAnnotation.class,
+ TestResource.class,
+ RequestScopeResource.class,
+ PerLookupScopeResource.class,
+ SingletonScopeResource.class);
+
+ final Resource.Builder resourceBuilder1 = Resource.builder();
+ resourceBuilder1.name("resource-programmatic/instance/").path("programmatic/instance/").addMethod("GET")
+ .handledBy(new Inflector<ContainerRequestContext, Response>() {
+ private int counter = 1;
+
+ @Override
+ public Response apply(ContainerRequestContext data) {
+ return Response.ok("prg-instance:" + counter++).build();
+ }
+ });
+ resourceConfig.registerResources(resourceBuilder1.build());
+
+ final Resource.Builder resourceBuilder2 = Resource.builder();
+ resourceBuilder2.name("resource-programmatic/singleton/").path("programmatic/singleton/").addMethod("GET")
+ .handledBy(SingletonProgrammatic.class);
+ resourceConfig.registerResources(resourceBuilder2.build());
+
+ final Resource.Builder resourceBuilder3 = Resource.builder();
+ resourceBuilder3.name("resource-programmatic/reused-singleton/").path("programmatic/reused-singleton/").addMethod("GET")
+ .handledBy(SubResourceSingleton.class);
+ resourceConfig.registerResources(resourceBuilder3.build());
+
+ final Resource.Builder resourceBuilder4 = Resource.builder();
+ resourceBuilder4.name("resource-programmatic/not-singleton/").path("programmatic/not-singleton/").addMethod("GET")
+ .handledBy(NotSingletonProgrammatic.class);
+ resourceConfig.registerResources(resourceBuilder4.build());
+
+ return resourceConfig;
+ }
+
+ @Test
+ public void singletonResourceTest() {
+ String str;
+ str = target().path("singleton").request().get().readEntity(String.class);
+ assertEquals("res:1", str);
+
+ str = target().path("singleton").request().get().readEntity(String.class);
+ assertEquals("res:2", str);
+
+ str = target().path("singleton/sub").request().get().readEntity(String.class);
+ assertEquals("sub:1", str);
+
+ str = target().path("singleton").request().get().readEntity(String.class);
+ assertEquals("res:3", str);
+
+ str = target().path("singleton/sub").request().get().readEntity(String.class);
+ assertEquals("sub:2", str);
+
+ str = target().path("singleton/sub-not-singleton").request().get().readEntity(String.class);
+ assertEquals("not-singleton:1", str);
+
+ str = target().path("singleton/sub-not-singleton").request().get().readEntity(String.class);
+ assertEquals("not-singleton:1", str);
+
+ str = target().path("singleton/instance").request().get().readEntity(String.class);
+ assertEquals("sub:1", str);
+
+ str = target().path("singleton/instance").request().get().readEntity(String.class);
+ assertEquals("sub:1", str);
+
+ str = target().path("singleton/sub").request().get().readEntity(String.class);
+ assertEquals("sub:3", str);
+
+ // one instance
+ str = target().path("programmatic").path("instance").request().get().readEntity(String.class);
+ assertEquals("prg-instance:1", str);
+
+ str = target().path("programmatic").path("instance").request().get().readEntity(String.class);
+ assertEquals("prg-instance:2", str);
+
+ // singleton
+ str = target().path("programmatic").path("singleton").request().get().readEntity(String.class);
+ assertEquals("prg-singleton:1", str);
+
+ str = target().path("programmatic").path("singleton").request().get().readEntity(String.class);
+ assertEquals("prg-singleton:2", str);
+
+ // request to the SubResourceSingleton (same class as sub resource on path "singleton/sub")
+ str = target().path("programmatic").path("reused-singleton").request().get().readEntity(String.class);
+ assertEquals("reused-singleton:4", str);
+
+ // not singleton
+ str = target().path("programmatic").path("not-singleton").request().get().readEntity(String.class);
+ assertEquals("prg-not-singleton:1", str);
+
+ str = target().path("programmatic").path("not-singleton").request().get().readEntity(String.class);
+ assertEquals("prg-not-singleton:1", str);
+ }
+
+ @Test
+ public void singletonAnnotationInheritedTest() {
+ // Singleton annotation is not inherited
+ String str;
+ str = target().path("inherit").request().get().readEntity(String.class);
+ assertEquals("inherit:1", str);
+
+ str = target().path("inherit").request().get().readEntity(String.class);
+ assertEquals("inherit:1", str);
+ }
+
+ @Test
+ public void singletonAnnotationInterfaceTest() {
+ // Singleton annotation is not inherited
+ String str;
+ str = target().path("interface").request().get().readEntity(String.class);
+ assertEquals("interface:1", str);
+
+ str = target().path("interface").request().get().readEntity(String.class);
+ assertEquals("interface:1", str);
+
+ }
+
+ /**
+ * Tests that resources are by default managed in {@link org.glassfish.jersey.process.internal.RequestScope request scope}.
+ */
+ @Test
+ public void testResourceInRequestScope() {
+ String str = target().path("testScope/request").request().get().readEntity(String.class);
+ assertEquals("same-instances", str);
+ }
+
+ @Test
+ public void testResourceInPerLookupScope() {
+ String str = target().path("testScope/perlookup").request().get().readEntity(String.class);
+ assertEquals("different-instances", str);
+ }
+
+ @Test
+ public void testResourceInSingletonScope() {
+ String str = target().path("testScope/singleton").request().get().readEntity(String.class);
+ assertEquals("same-instances", str);
+ }
+
+ @Path("test-requestScope")
+ public static class RequestScopeResource {
+
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Path("test-perlookupScope")
+ @PerLookup
+ public static class PerLookupScopeResource {
+
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Path("test-singletonScope")
+ @Singleton
+ public static class SingletonScopeResource {
+
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Path("testScope")
+ public static class TestResource {
+
+ @Inject
+ InjectionManager injectionManager;
+
+ private String compareInstances(Class<?> clazz) {
+ final Object res1 = Injections.getOrCreate(injectionManager, clazz);
+ final Object res2 = Injections.getOrCreate(injectionManager, clazz);
+ return (res1 == res2) ? "same-instances" : "different-instances";
+ }
+
+ @GET
+ @Path("request")
+ public String compareRequestScopedInstances() {
+ return compareInstances(RequestScopeResource.class);
+ }
+
+ @GET
+ @Path("perlookup")
+ public String comparePerLookupScopedInstances() {
+ return compareInstances(PerLookupScopeResource.class);
+ }
+
+ @GET
+ @Path("singleton")
+ public String compareSingletonInstances() {
+ return compareInstances(SingletonScopeResource.class);
+ }
+ }
+
+ @Singleton
+ public static class Parent {
+
+ }
+
+ @Path("inherit")
+ public static class ChildInheritsParentAnnotation extends Parent {
+
+ private int counter = 1;
+
+ @GET
+ public String get() {
+ return "inherit:" + counter++;
+ }
+ }
+
+ @Singleton
+ public static interface AnnotatedBySingleton {
+ }
+
+ @Path("interface")
+ public static class ChildImplementsInterfaceAnnotation implements AnnotatedBySingleton {
+
+ private int counter = 1;
+
+ @GET
+ public String get() {
+ return "interface:" + counter++;
+ }
+ }
+
+ @Singleton
+ public static class SingletonProgrammatic implements Inflector<Request, Response> {
+
+ private int counter = 1;
+
+ @Override
+ public Response apply(Request data) {
+ return Response.ok("prg-singleton:" + counter++).build();
+ }
+
+ }
+
+ public static class NotSingletonProgrammatic implements Inflector<Request, Response> {
+
+ private int counter = 1;
+
+ @Override
+ public Response apply(Request data) {
+ return Response.ok("prg-not-singleton:" + counter++).build();
+ }
+
+ }
+
+ @Singleton
+ @Path("singleton")
+ public static class SingletonResource {
+
+ private int counter = 1;
+
+ @GET
+ @Produces("text/html")
+ public String getCounter() {
+ return "res:" + (counter++);
+ }
+
+ @Path("sub")
+ public Class getSubResourceSingleton() {
+ return SubResourceSingleton.class;
+ }
+
+ @Path("sub-not-singleton")
+ public Class getSubResource() {
+ return SubResource.class;
+ }
+
+ @Path("instance")
+ public Object getSubResourceInstance() {
+ return new SubResourceSingleton();
+ }
+
+ @GET
+ @Path("filter")
+ public String getCounterFromFilter(@HeaderParam("counter") int counter) {
+ return "filter:" + counter;
+ }
+
+ }
+
+ @Singleton
+ public static class SubResourceSingleton implements Inflector<Request, Response> {
+
+ private int counter = 1;
+
+ @GET
+ public String getInternalCounter() {
+ return "sub:" + (counter++);
+ }
+
+ @Override
+ public Response apply(Request request) {
+ return Response.ok("reused-singleton:" + counter++).build();
+ }
+ }
+
+ public static class SubResource {
+
+ private int counter = 1;
+
+ @GET
+ public String getInternalCounter() {
+ return "not-singleton:" + (counter++);
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/StreamMethodCallTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/StreamMethodCallTest.java
new file mode 100644
index 0000000..7443489
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/StreamMethodCallTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests that appropriate methods are called in the intercepted output stream.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class StreamMethodCallTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestWriterInterceptor.class, TestResource.class);
+ }
+
+ public static class TestWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final OutputStream outputStreamoldOs = context.getOutputStream();
+ context.setOutputStream(new TestOutputStream(new GZIPOutputStream(outputStreamoldOs)));
+ context.proceed();
+ }
+ }
+
+ public static class TestOutputStream extends OutputStream {
+ private final GZIPOutputStream gzos;
+ public static boolean closeCalled = false;
+ public static boolean flushCalledBeforeClose = false;
+ public static boolean writeCalled = false;
+
+ public TestOutputStream(GZIPOutputStream gzos) {
+ this.gzos = gzos;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ writeCalled = true;
+ gzos.write(b);
+ }
+
+ @Override
+ public void close() throws IOException {
+ TestOutputStream.closeCalled = true;
+ gzos.close();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (!closeCalled) {
+ flushCalledBeforeClose = true;
+ }
+ gzos.flush();
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+ @GET
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Test
+ public void testCalledMethods() {
+ final Response response = target().path("resource").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertTrue("close() has not been called.", TestOutputStream.closeCalled);
+ Assert.assertTrue("flush() has not been called before close().", TestOutputStream.flushCalledBeforeClose);
+ Assert.assertTrue("write() has not been called.", TestOutputStream.writeCalled);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubResourceTest.java
new file mode 100644
index 0000000..5ce4830
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubResourceTest.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Sub-resource access/processing E2E tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @author Miroslav Fuksa
+ */
+public class SubResourceTest extends JerseyTest {
+
+ @Path("root/sub")
+ public static class Resource {
+ @Path("/")
+ public SubResource getSubResourceLocator() {
+ return new SubResource();
+ }
+
+ @Path("sub2")
+ public SubResource getSubResourceLocator2() {
+ return new SubResource();
+ }
+
+ static final String GET = "get";
+
+ @Path("some/path")
+ @GET
+ public String get() {
+ return GET;
+ }
+
+ @Path("empty-locator")
+ public EmptySubResourceClass getEmptyLocator() {
+ return new EmptySubResourceClass();
+ }
+ }
+
+ public static class SubResource {
+ public static final String MESSAGE = "Got it!";
+
+ @GET
+ public String getIt() {
+ return MESSAGE;
+ }
+
+
+ @POST
+ public String post(String str) {
+ return str;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, LocatorAndMethodResource.class, EmptyRootResource.class);
+ }
+
+ /**
+ * Test concurrent sub-resource access. (See JERSEY-1421).
+ *
+ * @throws Exception in case of test failure.
+ */
+ @Test
+ public void testConcurrentSubResourceAccess() throws Exception {
+ final WebTarget subResource = target("root/sub/sub2");
+
+ final int MAX = 25;
+
+ final List<Future<String>> results = new ArrayList<Future<String>>(MAX);
+ for (int i = 0; i < MAX; i++) {
+ results.add(subResource.request().async().get(String.class));
+ }
+
+ for (Future<String> resultFuture : results) {
+ assertEquals(SubResource.MESSAGE, resultFuture.get());
+ }
+ }
+
+ @Test
+ public void subResourceTest() throws Exception {
+ Response response = target("root/sub/sub2").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(SubResource.MESSAGE, response.readEntity(String.class));
+
+ response = target("root/sub/sub2").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(SubResource.MESSAGE, response.readEntity(String.class));
+ }
+
+ @Test
+ public void subResourceWithoutPathTest() throws Exception {
+ Response response = target("root/sub").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(SubResource.MESSAGE, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ Response response = target("root/sub/some/path").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(Resource.GET, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPost() throws Exception {
+ Response response = target("root/sub/sub2").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("post", response.readEntity(String.class));
+ }
+
+ // this resource class will report warning during validation, but should be loaded
+ @Path("locator-and-method")
+ public static class LocatorAndMethodResource {
+ @GET
+ @Path("sub")
+ public String getSub() {
+ return "get";
+ }
+
+ @Path("sub")
+ public PostSubResource getSubResourceSub() {
+ return new PostSubResource();
+ }
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @Path("/")
+ public PostSubResource getSubResource() {
+ return new PostSubResource();
+ }
+ }
+
+ public static class PostSubResource {
+ @GET
+ public String get() {
+ return "fail: locator get should never be called !!!";
+ }
+
+ @POST
+ public String post(String post) {
+ return "fail: post should never be called !!!";
+ }
+
+ @GET
+ @Path("inner")
+ public String getInner() {
+ return "inner";
+ }
+ }
+
+ @Test
+ public void testGetIsCalled() throws Exception {
+ Response response = target("locator-and-method").request().get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ Assert.assertEquals("get", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGetIsCalledInSub() throws Exception {
+ Response response = target("locator-and-method/sub").request().get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ Assert.assertEquals("get", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGetIsCalledInInner() throws Exception {
+ Response response = target("locator-and-method/inner").request().get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ Assert.assertEquals("inner", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGetIsCalledInSubInner() throws Exception {
+ Response response = target("locator-and-method/sub/inner").request().get();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ Assert.assertEquals("inner", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPostShouldNeverBeCalled() throws Exception {
+ Response response = target("locator-and-method").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(Response.Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ public void testPostShouldNeverBeCalledInSub() throws Exception {
+ Response response = target("locator-and-method/sub").request().post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(Response.Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
+ }
+
+ @Path("empty-root")
+ public static class EmptyRootResource {
+
+ }
+
+ @Test
+ public void testCallEmptyResource() throws Exception {
+ Response response = target("empty-root").request().get();
+ Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
+ }
+
+ public static class EmptySubResourceClass {
+ // empty
+ }
+
+ @Test
+ public void testCallEmptySubResource() throws Exception {
+ Response response = target("empty-locator").request().get();
+ Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubjectSecurityContextTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubjectSecurityContextTest.java
new file mode 100644
index 0000000..6d2d583
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SubjectSecurityContextTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotAcceptableException;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.SubjectSecurityContext;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test subject based security context. Make sure resource
+ * and sub-resource methods/locators are invoked
+ * via {@link SubjectSecurityContext#doAsSubject(java.security.PrivilegedAction)} method.
+ *
+ * @author Martin Matula
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class SubjectSecurityContextTest extends JerseyTest {
+
+ // actual filter reference to keep track of the invocations
+ SubjectSecurityContextSettingFilter subjectFilter;
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class).registerInstances(subjectFilter = new SubjectSecurityContextSettingFilter());
+ }
+
+ @Path("/resource")
+ public static class Resource {
+
+ @GET
+ public String resourceGet() {
+ return "Resource GET";
+ }
+
+ @Path("subresource")
+ public SubResource getSubResource() {
+ return new SubResource();
+ }
+
+ @Path("subresource-wae")
+ public SubResource getSubResourceEx() {
+ throw new NotAcceptableException(Response.notAcceptable(null).entity("Not Acceptable SRL").build());
+ }
+
+ @Path("sub-get")
+ @GET
+ public String getSub() {
+ return "Resource sub-GET";
+ }
+
+ @Path("sub-get-wae")
+ @GET
+ public String getSubEx() {
+ throw new NotAcceptableException(Response.notAcceptable(null).entity("Not Acceptable Resource sub-GET").build());
+ }
+ }
+
+ public static class SubResource {
+ @GET
+ public String subResourceGet() {
+ return "SubResource GET";
+ }
+
+ @Path("wae")
+ @GET
+ public String subResourceGetEx() {
+ throw new NotAcceptableException(Response.notAcceptable(null).entity("Not Acceptable SubResource GET").build());
+ }
+ }
+
+ /**
+ * Custom SubjectSecurityContext that keeps number of doAsSubject invocations.
+ */
+ public static class MySubjectSecurityContext implements SubjectSecurityContext {
+
+ // no hits so far
+ int hits = 0;
+
+ @Override
+ public Object doAsSubject(PrivilegedAction action) {
+ hits++;
+ return action.run();
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isUserInRole(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isSecure() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ /**
+ * Custom filter to set the custom subject security context on every request before the request get matched,
+ * so that sub-resource locator invocations have a chance to see the subject security context set.
+ */
+ @PreMatching
+ @Provider
+ public static class SubjectSecurityContextSettingFilter implements ContainerRequestFilter {
+
+ private final MySubjectSecurityContext securityContext = new MySubjectSecurityContext();
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ requestContext.setSecurityContext(securityContext);
+ }
+
+ /**
+ * Provide actual doAsSubject hit count.
+ *
+ * @return number of doAsSubject invocations.
+ */
+ public int getHits() {
+ return securityContext.hits;
+ }
+ }
+
+ @Test
+ public void testSubjectSecurityContext() {
+
+ WebTarget r = target("/resource");
+
+ assertThat(r.request().get(String.class), equalTo("Resource GET"));
+ assertThat(subjectFilter.getHits(), equalTo(1)); // one resource method invoked
+
+ assertThat(r.path("subresource").request().get(String.class), equalTo("SubResource GET"));
+ assertThat(subjectFilter.getHits(), equalTo(3)); // + one sub-resource locator and one resource method invoked
+
+ assertThat("Resource sub-GET", equalTo(r.path("sub-get").request().get(String.class)));
+ assertThat(subjectFilter.getHits(), equalTo(4)); // + one sub-resource method invoked
+
+ Response response;
+
+ response = r.path("sub-get-wae").request().get();
+ assertThat(response.getStatus(), equalTo(Response.Status.NOT_ACCEPTABLE.getStatusCode()));
+ assertThat(response.readEntity(String.class), equalTo("Not Acceptable Resource sub-GET"));
+ assertThat(subjectFilter.getHits(), equalTo(5)); // + one sub-resource method invoked
+
+ response = r.path("subresource-wae").request().get();
+ assertThat(response.getStatus(), equalTo(Response.Status.NOT_ACCEPTABLE.getStatusCode()));
+ assertThat(response.readEntity(String.class), equalTo("Not Acceptable SRL"));
+ assertThat(subjectFilter.getHits(), equalTo(6));
+
+ response = r.path("subresource/wae").request().get();
+ assertThat(response.getStatus(), equalTo(Response.Status.NOT_ACCEPTABLE.getStatusCode()));
+ assertThat(response.readEntity(String.class), equalTo("Not Acceptable SubResource GET"));
+ assertThat(subjectFilter.getHits(), equalTo(8)); // + one sub-resource locator and one resource method invoked
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/UriBuilderTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/UriBuilderTemplateTest.java
new file mode 100644
index 0000000..f30c82c
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/UriBuilderTemplateTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing URI template as an e2e test.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class UriBuilderTemplateTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testNumericResource() {
+ Response response = target().path("test/numeric/55").request().get();
+ String uri = response.readEntity(String.class);
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals("test/numeric/55", uri);
+ }
+
+ @Test
+ public void testAnyResource() {
+ Response response = target().path("test/any/getNumericResource").request().get();
+ String uri = response.readEntity(String.class);
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals("test/numeric/11", uri);
+ }
+
+ @Path("test")
+ public static class Resource {
+
+ @Path("numeric/{ resourceNo : \\d+}")
+ @GET
+ public String getNumericResource(@PathParam("resourceNo") int resourceNo) {
+ URI anyResourceUri = UriBuilder.fromResource(Resource.class).path(Resource.class,
+ "getNumericResource").build(resourceNo);
+ return anyResourceUri.toString();
+ }
+
+ @Path("any/{resourceName}")
+ @GET
+ public String getAnyResource(@PathParam("resourceName") String resourceName) {
+ URI numResourceUri = UriBuilder.fromResource(Resource.class).path(Resource.class, "getNumericResource").build(11);
+ return numResourceUri.toString();
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testResolveTemplate() {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("a", "xyz");
+ map.put(null, "path");
+ UriBuilder builder = UriBuilder.fromPath("").path("{a}/{b}");
+ builder.resolveTemplates(map);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/WebApplicationExceptionLoggingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/WebApplicationExceptionLoggingTest.java
new file mode 100644
index 0000000..7f07197
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/WebApplicationExceptionLoggingTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import javax.validation.ValidationException;
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests that {@link WebApplicationException} is logged on the correct level.
+ *
+ * @author Miroslav Fuksa
+ */
+public class WebApplicationExceptionLoggingTest extends JerseyTest {
+
+ @Path("/test")
+ public static class StatusResource {
+
+ @GET
+ @Produces("text/plain")
+ public String test(@NotNull @QueryParam("id") final String id) {
+ return "ok";
+ }
+
+ @GET
+ @Path("WAE-no-entity")
+ @Produces("text/plain")
+ public String testWithoutEntity() {
+ throw new WebApplicationException("WAE without entity", Response.status(400).build());
+ }
+
+ @GET
+ @Path("WAE-entity")
+ @Produces("text/plain")
+ public String testWithEntity() {
+ throw new WebApplicationException("WAE with entity", Response.status(400).entity("WAE with entity").build());
+ }
+ }
+
+ @Provider
+ public static class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
+
+ @Override
+ public Response toResponse(final ValidationException ex) {
+ return Response.status(200).entity("Error mapped: " + ex.toString()).type("text/plain").build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINER.intValue());
+
+ return new ResourceConfig(StatusResource.class, ValidationExceptionMapper.class);
+ }
+
+ private LogRecord getLogRecord(final String messagePrefix) {
+ for (final LogRecord logRecord : getLoggedRecords()) {
+ if (logRecord.getMessage() != null && logRecord.getMessage().startsWith(messagePrefix)) {
+ return logRecord;
+ }
+ }
+ return null;
+ }
+
+ @Test
+ public void testValidationException() {
+ final Response response = target().path("test").request().get();
+ assertEquals(200, response.getStatus());
+
+ final String entity = response.readEntity(String.class);
+ assertTrue(entity.startsWith("Error mapped:"));
+
+ // check logs
+ final LogRecord logRecord = this.getLogRecord("Starting mapping of the exception");
+ assertNotNull(logRecord);
+ assertEquals(Level.FINER, logRecord.getLevel());
+
+ // check that there is no exception logged on the level higher than FINE
+ for (final LogRecord record : getLoggedRecords()) {
+ if (record.getThrown() != null) {
+ assertTrue(record.getLevel().intValue() <= Level.FINE.intValue());
+ }
+ }
+
+ }
+
+ @Test
+ public void testWAEWithEntity() {
+ final Response response = target().path("test/WAE-entity").request().get();
+ assertEquals(400, response.getStatus());
+ final String entity = response.readEntity(String.class);
+ assertEquals("WAE with entity", entity);
+
+ // check logs
+ LogRecord logRecord = this.getLogRecord("Starting mapping of the exception");
+ assertNotNull(logRecord);
+ assertEquals(Level.FINER, logRecord.getLevel());
+
+ logRecord = this.getLogRecord("WebApplicationException (WAE) with non-null entity thrown.");
+ assertNotNull(logRecord);
+ assertEquals(Level.FINE, logRecord.getLevel());
+ assertTrue(logRecord.getThrown() instanceof WebApplicationException);
+ logRecord.getThrown().printStackTrace();
+ }
+
+ @Test
+ public void testWAEWithoutEntity() {
+ final Response response = target().path("test/WAE-no-entity").request().get();
+ assertEquals(400, response.getStatus());
+ assertFalse(response.hasEntity());
+
+ // check logs
+ LogRecord logRecord = this.getLogRecord("Starting mapping of the exception");
+ assertNotNull(logRecord);
+ assertEquals(Level.FINER, logRecord.getLevel());
+
+ logRecord = this.getLogRecord("WebApplicationException (WAE) with no entity thrown and no");
+ assertNotNull(logRecord);
+ assertEquals(Level.FINE, logRecord.getLevel());
+ assertTrue(logRecord.getThrown() instanceof WebApplicationException);
+ logRecord.getThrown().printStackTrace();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/PostToPutDeleteTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/PostToPutDeleteTest.java
new file mode 100644
index 0000000..414159a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/PostToPutDeleteTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.filter.HttpMethodOverrideFilter;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Martin Matula
+ */
+public class PostToPutDeleteTest extends JerseyTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get(@QueryParam("a") String a) {
+ return "GET: " + a;
+ }
+
+ @PUT
+ public String put() {
+ return "PUT";
+ }
+
+ @DELETE
+ public String delete() {
+ return "DELETE";
+ }
+
+ @POST
+ public String post() {
+ return "POST";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HttpMethodOverrideFilter.class, Resource.class);
+ }
+
+ @Test
+ public void testPut() {
+ assertResponseEquals("PUT,PUT,PUT,", _test("PUT"));
+ }
+
+ @Test
+ public void testDelete() {
+ assertResponseEquals("DELETE,DELETE,DELETE,", _test("DELETE"));
+ }
+
+ @Test
+ public void testGet() {
+ assertResponseEquals("GET: test,GET: test,GET: test,", _test("GET"));
+ }
+
+ @Test
+ public void testConflictingMethods() {
+ Response cr = target("/").queryParam("_method", "PUT").request()
+ .header("X-HTTP-Method-Override", "DELETE").post(Entity.text(""));
+ assertEquals(400, cr.getStatus());
+ }
+
+ @Test
+ public void testUnsupportedMethod() {
+ assertResponseEquals("405,405,405,", _test("PATCH"));
+ }
+
+ @Test
+ public void testGetWithQueryParam() {
+ String result = target().queryParam("_method", "GET").queryParam("a", "test").request().post(null, String.class);
+ assertEquals("GET: test", result);
+ }
+
+ @Test
+ public void testGetWithOtherEntity() {
+ String result = target().queryParam("_method", "GET").request().post(Entity.text("a=test"), String.class);
+ assertEquals("GET: null", result);
+ }
+
+ @Test
+ public void testPlainPost() {
+ String result = target().request().post(null, String.class);
+ assertEquals("POST", result);
+ }
+
+ public Response[] _test(String method) {
+ Response[] result = new Response[3];
+ WebTarget target = target();
+
+ result[0] = target.request().header("X-HTTP-Method-Override", method)
+ .post(Entity.form(new Form().param("a", "test")));
+ result[1] = target.queryParam("_method", method).request()
+ .post(Entity.form(new Form().param("a", "test")));
+ result[2] = target.queryParam("_method", method).request().header("X-HTTP-Method-Override", method)
+ .post(Entity.form(new Form().param("a", "test")));
+ return result;
+ }
+
+ public void assertResponseEquals(String expected, Response[] responses) {
+ StringBuilder result = new StringBuilder();
+
+ for (Response r : responses) {
+ if (r.getStatus() == Response.Status.OK.getStatusCode()) {
+ result.append(r.readEntity(String.class));
+ } else {
+ result.append(r.getStatus());
+ }
+ result.append(",");
+ }
+
+ assertEquals(expected, result.toString());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/RolesAllowedTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/RolesAllowedTest.java
new file mode 100644
index 0000000..4dda6f3
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/RolesAllowedTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import java.security.Principal;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import javax.annotation.Priority;
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class RolesAllowedTest extends JerseyTest {
+
+ @PreMatching
+ @Priority(Priorities.AUTHENTICATION)
+ public static class SecurityFilter implements ContainerRequestFilter {
+
+ public void filter(final ContainerRequestContext request) {
+ final String user = request.getHeaders().getFirst("X-USER");
+ request.setSecurityContext(new Authenticator(user));
+ }
+
+ private static class Authenticator implements SecurityContext {
+
+ private final Principal principal;
+
+ Authenticator(final String name) {
+ principal = name == null
+ ? null
+ : new Principal() {
+ public String getName() {
+ return name;
+ }
+ };
+ }
+
+ public Principal getUserPrincipal() {
+ return principal;
+ }
+
+ public boolean isUserInRole(final String role) {
+ return role.equals(principal.getName()) || ("user".equals(role) && "admin".equals(principal.getName()));
+ }
+
+ public boolean isSecure() {
+ return false;
+ }
+
+ public String getAuthenticationScheme() {
+ return "";
+ }
+ }
+ }
+
+ @Path("/")
+ @PermitAll
+ public static class Resource {
+
+ @RolesAllowed("user")
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @RolesAllowed("admin")
+ @POST
+ public String post(final String content) {
+ return content;
+ }
+
+ @Path("sub")
+ public SubResource getSubResource() {
+ return new SubResource();
+ }
+ }
+
+ @RolesAllowed("admin")
+ public static class SubResource {
+
+ @Path("deny-all")
+ @DenyAll
+ @GET
+ public String denyAll() {
+ return "GET";
+ }
+
+ @Path("permit-all")
+ @PermitAll
+ @GET
+ public String permitAll() {
+ return "GET";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, RolesAllowedDynamicFeature.class, SecurityFilter.class);
+ }
+
+ @Test
+ public void testGetAsUser() {
+ assertEquals("GET", target().request().header("X-USER", "user").get(String.class));
+ }
+
+ @Test
+ public void testGetAsAdmin() {
+ assertEquals("GET", target().request().header("X-USER", "admin").get(String.class));
+ }
+
+ @Test
+ public void testPostAsUser() {
+ final Response cr = target().request().header("X-USER", "user").post(Entity.text("POST"));
+ assertEquals(403, cr.getStatus());
+ }
+
+ @Test
+ public void testPostAsAdmin() {
+ assertEquals("POST", target().request().header("X-USER", "admin").post(Entity.text("POST"), String.class));
+ }
+
+ @Test
+ public void testDenyAll() {
+ assertEquals(403, target("sub/deny-all").request().header("X-USER", "admin").get().getStatus());
+ }
+
+ @Test
+ public void testPermitAll() {
+ assertEquals("GET", target("sub/permit-all").request().header("X-USER", "xyz").get(String.class));
+ }
+
+ @Test
+ public void testNotAuthorized() {
+ assertThat("User should not be authorized.", target().request().get().getStatus(), is(403));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeNegativeTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeNegativeTest.java
new file mode 100644
index 0000000..4c191dd
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeNegativeTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * No activation property ({@value org.glassfish.jersey.server.ServerProperties#LANGUAGE_MAPPINGS},
+ * {@value org.glassfish.jersey.server.ServerProperties#MEDIA_TYPE_MAPPINGS}) is set into {@link ResourceConfig} which should
+ * lead to point that {@link org.glassfish.jersey.server.filter.UriConnegFilter} is not registered.
+ *
+ * @author Michal Gajdos
+ */
+public class UriConnegLanguageMediaTypeNegativeTest extends JerseyTest {
+
+ @Path("/abc")
+ public static class LanguageVariantResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ final List<Variant> variants = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.valueOf("application/foo"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .mediaTypes(MediaType.valueOf("application/bar"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .build();
+
+ final Variant variant = r.selectVariant(variants);
+ if (variant == null) {
+ return Response.notAcceptable(variants).build();
+ } else {
+ return Response.ok(variant.getMediaType().toString() + ", " + variant.getLanguage(), variant).build();
+ }
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(LanguageVariantResource.class).register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testMediaTypesAndLanguagesNegative() {
+ _test("english", "foo", "en", "application/foo");
+ _test("french", "foo", "fr", "application/foo");
+
+ _test("english", "bar", "en", "application/bar");
+ _test("french", "bar", "fr", "application/bar");
+ }
+
+ private void _test(String ul, String um, String l, String m) {
+ Response response = target().path("abc." + ul + "." + um).request().get();
+ assertEquals(404, response.getStatus());
+
+ response = target().path("abc." + um + "." + ul).request().get();
+ assertEquals(404, response.getStatus());
+
+ response = target().path("abc").request(m).header(HttpHeaders.ACCEPT_LANGUAGE, l).get();
+ assertEquals(m + ", " + l, response.readEntity(String.class));
+ assertEquals(l, response.getLanguage().toString());
+ assertEquals(m, response.getMediaType().toString());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeTest.java
new file mode 100644
index 0000000..635b499
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageMediaTypeTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class UriConnegLanguageMediaTypeTest extends JerseyTest {
+
+ @Path("/abc")
+ public static class LanguageVariantResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ final List<Variant> variants = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.valueOf("application/foo"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .mediaTypes(MediaType.valueOf("application/bar"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .build();
+
+ final Variant variant = r.selectVariant(variants);
+ if (variant == null) {
+ return Response.notAcceptable(variants).build();
+ } else {
+ return Response.ok(variant.getMediaType().toString() + ", " + variant.getLanguage(), variant).build();
+ }
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ Map<String, MediaType> mediaTypes = new HashMap<>();
+ mediaTypes.put("foo", MediaType.valueOf("application/foo"));
+ mediaTypes.put("bar", MediaType.valueOf("application/bar"));
+
+ Map<String, String> languages = new HashMap<>();
+ languages.put("english", "en");
+ languages.put("french", "fr");
+
+ ResourceConfig rc = new ResourceConfig(LanguageVariantResource.class);
+ rc.property(ServerProperties.LANGUAGE_MAPPINGS, languages);
+ rc.property(ServerProperties.MEDIA_TYPE_MAPPINGS, mediaTypes);
+ return rc;
+ }
+
+ @Test
+ public void testMediaTypesAndLanguages() {
+ _test("english", "foo", "en", "application/foo");
+ _test("french", "foo", "fr", "application/foo");
+
+ _test("english", "bar", "en", "application/bar");
+ _test("french", "bar", "fr", "application/bar");
+ }
+
+ private void _test(String ul, String um, String l, String m) {
+ Response r = target().path("abc." + ul + "." + um).request().get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+
+ r = target().path("abc." + um + "." + ul).request().get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+
+ r = target().path("abc").request(m).header(HttpHeaders.ACCEPT_LANGUAGE, l).get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageTest.java
new file mode 100644
index 0000000..25b537b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegLanguageTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class UriConnegLanguageTest extends JerseyTest {
+
+ @Path("/abc")
+ public static class LanguageVariantResource {
+
+ @GET
+ public Response doGet(@Context Request request, @Context HttpHeaders headers) {
+
+ assertEquals(1, headers.getAcceptableLanguages().size());
+
+ List<Variant> vs = Variant.VariantListBuilder.newInstance()
+ .languages(new Locale("zh"))
+ .languages(new Locale("fr"))
+ .languages(new Locale("en")).add()
+ .build();
+
+ Variant v = request.selectVariant(vs);
+ if (v == null) {
+ return Response.notAcceptable(vs).build();
+ } else {
+ return Response.ok(v.getLanguage().toString(), v).build();
+ }
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ Map<String, String> languages = new HashMap<>();
+ languages.put("english", "en");
+ languages.put("french", "fr");
+
+ ResourceConfig rc = new ResourceConfig(LanguageVariantResource.class);
+ rc.property(ServerProperties.LANGUAGE_MAPPINGS, languages);
+ return rc;
+ }
+
+ @Test
+ public void testLanguages() {
+ Response response = target().path("abc.english").request().get();
+ assertEquals("en", response.readEntity(String.class));
+ assertEquals("en", response.getLanguage().toString());
+
+ response = target().path("abc.french").request().get();
+ assertEquals("fr", response.readEntity(String.class));
+ assertEquals("fr", response.getLanguage().toString());
+
+ response = target().path("abc.french").request().header(HttpHeaders.ACCEPT_LANGUAGE, "en").get();
+ assertEquals("fr", response.readEntity(String.class));
+ assertEquals("fr", response.getLanguage().toString());
+
+ response = target().path("abc").request().header(HttpHeaders.ACCEPT_LANGUAGE, "en").get();
+ assertEquals("en", response.readEntity(String.class));
+ assertEquals("en", response.getLanguage().toString());
+
+ response = target().path("abc").request().header(HttpHeaders.ACCEPT_LANGUAGE, "fr").get();
+ assertEquals("fr", response.readEntity(String.class));
+ assertEquals("fr", response.getLanguage().toString());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromProperty.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromProperty.java
new file mode 100644
index 0000000..c80ed48
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromProperty.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * @author Martin Matula
+ */
+public class UriConnegMappingFromProperty extends UriConnegLanguageMediaTypeTest {
+
+ @Override
+ protected Application configure() {
+ ResourceConfig rc = new ResourceConfig(UriConnegLanguageMediaTypeTest.LanguageVariantResource.class);
+ rc.property(ServerProperties.MEDIA_TYPE_MAPPINGS, "foo : application/foo, bar : application/bar");
+ rc.property(ServerProperties.LANGUAGE_MAPPINGS, "english : en, french : fr");
+ return rc;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromStringTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromStringTest.java
new file mode 100644
index 0000000..e7e0625
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMappingFromStringTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * @author Martin Matula
+ */
+public class UriConnegMappingFromStringTest extends UriConnegLanguageMediaTypeTest {
+
+ @Override
+ protected Application configure() {
+ ResourceConfig rc = new ResourceConfig(LanguageVariantResource.class);
+ rc.property(ServerProperties.LANGUAGE_MAPPINGS, "english : en, french : fr");
+ rc.property(ServerProperties.MEDIA_TYPE_MAPPINGS, "foo : application/foo, bar : application/bar");
+ return rc;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMediaTypeTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMediaTypeTest.java
new file mode 100644
index 0000000..f842a32
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/filter/UriConnegMediaTypeTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.filter;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ * @author Martin Matula
+ */
+public class UriConnegMediaTypeTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ Map<String, MediaType> mediaTypes = new HashMap<>();
+ mediaTypes.put("foo", MediaType.valueOf("application/foo"));
+ mediaTypes.put("bar", MediaType.valueOf("application/bar"));
+ mediaTypes.put("foot", MediaType.valueOf("application/foot"));
+
+ Set<Class<?>> classes = new HashSet<>();
+
+ for (Class<?> c : UriConnegMediaTypeTest.class.getClasses()) {
+ if (c.getAnnotation(Path.class) != null) {
+ classes.add(c);
+ }
+ }
+
+ ResourceConfig rc = new ResourceConfig(classes);
+ rc.property(ServerProperties.MEDIA_TYPE_MAPPINGS, mediaTypes);
+ return rc;
+ }
+
+ public abstract static class Base {
+ @GET
+ @Produces("application/foo")
+ public String doGetFoo(@Context HttpHeaders headers) {
+ assertEquals(1, headers.getAcceptableMediaTypes().size());
+ return "foo";
+ }
+
+ @GET
+ @Produces("application/foot")
+ public String doGetFoot() {
+ return "foot";
+ }
+
+ @GET
+ @Produces("application/bar")
+ public String doGetBar() {
+ return "bar";
+ }
+ }
+
+ @Path("/abc")
+ public static class SingleSegment extends Base {
+ }
+
+ @Path("/xyz/")
+ public static class SingleSegmentSlash extends Base {
+ }
+
+ @Path("/xyz/abc")
+ public static class MultipleSegments extends Base {
+ }
+
+ @Path("/xyz/xxx/")
+ public static class MultipleSegmentsSlash extends Base {
+ }
+
+ @Path("/xyz/abc.xml")
+ public static class DotPrefixSegments extends Base {
+ }
+
+ @Path("/foo_bar_foot")
+ public static class PathWithSuffixSegment extends Base {
+ }
+
+ @Path("/")
+ public static class SubResourceMethods extends Base {
+ @Path("sub")
+ @GET
+ @Produces("application/foo")
+ public String doGetFooS() {
+ return "foo";
+ }
+
+ @Path("sub")
+ @GET
+ @Produces("application/foot")
+ public String doGetFootS() {
+ return "foot";
+ }
+
+ @Path("sub")
+ @GET
+ @Produces("application/bar")
+ public String doGetBarS() {
+ return "bar";
+ }
+ }
+
+ @Test
+ public void testSlash() throws IOException {
+ _test("/");
+ }
+
+ @Test
+ public void testSingleSegment() throws IOException {
+ _test("/", "abc");
+ }
+
+ @Test
+ public void testSingleSegmentSlash() throws IOException {
+ _test("/", "xyz", "/");
+ }
+
+ @Test
+ public void testMultipleSegments() throws IOException {
+ _test("/xyz", "abc");
+ }
+
+ @Test
+ public void testMultipleSegmentsSlash() throws IOException {
+ _test("/xyz", "xxx", "/");
+ }
+
+ @Test
+ public void testDotPrefixSegments() throws IOException {
+ _test("/xyz", "abc.xml");
+ _test("/xyz", "abc", ".xml");
+ }
+
+ @Test
+ public void testXXXSegment() throws IOException {
+ _test("/", "foo_bar_foot");
+ }
+
+ @Test
+ public void testSubResourceMethods() throws IOException {
+ _test("/", "sub");
+ }
+
+ private void _test(String base) {
+ _test(base, "", "");
+ }
+
+ private void _test(String base, String path) {
+ _test(base, path, "");
+ }
+
+ private void _test(String base, String path, String terminate) {
+ WebTarget r = target().path(base);
+
+ String s = r.path(path + ".foo" + terminate).request().get(String.class);
+ assertEquals("foo", s);
+
+ s = r.path(path + ".foo" + terminate).request("application/bar").get(String.class);
+ assertEquals("foo", s);
+
+ s = r.path(path + ".foot" + terminate).request().get(String.class);
+ assertEquals("foot", s);
+
+ s = r.path(path + ".bar" + terminate).request().get(String.class);
+ assertEquals("bar", s);
+
+ s = r.path(path + terminate).request("application/foo").get(String.class);
+ assertEquals("foo", s);
+
+ s = r.path(path + terminate).request("application/foot").get(String.class);
+ assertEquals("foot", s);
+
+ s = r.path(path + terminate).request("application/foo;q=0.1").get(String.class);
+ assertEquals("foo", s);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ApplicationInfoTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ApplicationInfoTest.java
new file mode 100644
index 0000000..456b950
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ApplicationInfoTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+
+import javax.annotation.Priority;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.monitoring.ApplicationInfo;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * The test uses server properties {@link ServerProperties#MONITORING_STATISTICS_MBEANS_ENABLED},
+ * {@link ServerProperties#MONITORING_STATISTICS_MBEANS_ENABLED},
+ * {@link ServerProperties#MONITORING_STATISTICS_MBEANS_ENABLED}
+ * and it also implements {@link ForcedAutoDiscoverable} and tests if it is possible to inject
+ * {@link ApplicationInfo} in different circumstances.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ApplicationInfoTest extends JerseyTest {
+
+ private static final String FORCE_ENABLE = "FORCE_ENABLE";
+ private static final String ENABLE_MONITORING = "ENABLE_MONITORING";
+ private static final String ENABLE_MONITORING_STATISTICS = "ENABLE_MONITORING_STATISTICS";
+ private static final String ENABLE_MONITORING_STATISTICS_MBEANS = "ENABLE_MONITORING_STATISTICS_MBEANS";
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ //force, 3x AutoDiscoverable, 3x ResourceConfig, response
+ // no property set => 500
+ {false, false, false, false, null, null, null, 500},
+ // property set by ForcedAutoDiscoverable => 200
+ {false, true, false, false, null, null, null, 200},
+ {false, false, true, false, null, null, null, 200},
+ {false, false, false, true, null, null, null, 200},
+ // property disable by ResourceConfig => 500
+ {false, true, false, false, false, false, false, 500},
+ {false, false, true, false, false, false, false, 500},
+ {false, false, false, true, false, false, false, 500},
+ // property disable by ResourceConfig but forced by ForcedAutoDiscoverable => 200
+ {true, true, false, false, false, false, false, 200},
+ {true, false, true, false, false, false, false, 200},
+ {true, false, false, true, false, false, false, 200}
+ });
+ }
+
+ private int responseStatus;
+
+ public ApplicationInfoTest(boolean forceEnable, boolean enableMonitoring,
+ boolean enableMonitoringStatistics, boolean enableMonitoringStatisticsMBeans,
+ Boolean monitoringEnabled, Boolean monitoringStatisticsEnabled,
+ Boolean monitoringStatisticsMBeansEnabled, int responseStatus) {
+ super(createApplication(forceEnable, enableMonitoring,
+ enableMonitoringStatistics, enableMonitoringStatisticsMBeans,
+ monitoringEnabled, monitoringStatisticsEnabled,
+ monitoringStatisticsMBeansEnabled));
+ this.responseStatus = responseStatus;
+ }
+
+ private static Application createApplication(boolean forceEnable, boolean enableMonitoring,
+ boolean enableMonitoringStatistics, boolean enableMonitoringStatisticsMBeans,
+ Boolean monitoringEnabled, Boolean monitoringStatisticsEnabled,
+ Boolean monitoringStatisticsMBeansEnabled) {
+ final ResourceConfig resourceConfig = new ResourceConfig(Resource.class);
+ resourceConfig.property(ServerProperties.APPLICATION_NAME, "testApp");
+ resourceConfig.property(FORCE_ENABLE, forceEnable);
+ if (enableMonitoring) {
+ resourceConfig.property(ENABLE_MONITORING, true);
+ }
+ if (enableMonitoringStatistics) {
+ resourceConfig.property(ENABLE_MONITORING_STATISTICS, true);
+ }
+ if (enableMonitoringStatisticsMBeans) {
+ resourceConfig.property(ENABLE_MONITORING_STATISTICS_MBEANS, true);
+ }
+ if (monitoringEnabled != null) {
+ resourceConfig.property(ServerProperties.MONITORING_ENABLED, monitoringEnabled);
+ }
+ if (monitoringStatisticsEnabled != null) {
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_ENABLED, monitoringStatisticsEnabled);
+ }
+ if (monitoringStatisticsMBeansEnabled != null) {
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, monitoringStatisticsMBeansEnabled);
+ }
+
+ return resourceConfig;
+ }
+
+ @Test
+ public void test() {
+ final Response response = target().path("resource").request().get();
+ Assert.assertEquals(responseStatus, response.getStatus());
+ if (responseStatus == 200) {
+ Assert.assertEquals("testApp", response.readEntity(String.class));
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @Context
+ Provider<ApplicationInfo> applicationInfoProvider;
+
+ @GET
+ public String getAppName() {
+ final ApplicationInfo applicationInfo = applicationInfoProvider.get();
+ return applicationInfo.getResourceConfig().getApplicationName();
+ }
+ }
+
+ @ConstrainedTo(RuntimeType.SERVER)
+ @Priority(AutoDiscoverable.DEFAULT_PRIORITY - 1)
+ public static class ForcedAutoDiscoverableImpl implements ForcedAutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ final boolean forceEnable = PropertiesHelper.isProperty(context.getConfiguration().getProperty(FORCE_ENABLE));
+ if (PropertiesHelper.isProperty(context.getConfiguration().getProperty(ENABLE_MONITORING))) {
+ enable(context, forceEnable, ServerProperties.MONITORING_ENABLED);
+ }
+ if (PropertiesHelper.isProperty(context.getConfiguration().getProperty(ENABLE_MONITORING_STATISTICS))) {
+ enable(context, forceEnable, ServerProperties.MONITORING_STATISTICS_ENABLED);
+ }
+ if (PropertiesHelper.isProperty(context.getConfiguration().getProperty(ENABLE_MONITORING_STATISTICS_MBEANS))) {
+ enable(context, forceEnable, ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED);
+ }
+ }
+
+ private void enable(FeatureContext context, boolean forceEnable, String propertyName) {
+ if (forceEnable) {
+ context.property(propertyName, true);
+ } else {
+ if (context.getConfiguration().getProperty(propertyName) == null) {
+ context.property(propertyName, true);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/EventListenerTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/EventListenerTest.java
new file mode 100644
index 0000000..3bda9a9
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/EventListenerTest.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.glassfish.jersey.server.ManagedAsync;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.ResourceMethod;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class EventListenerTest extends JerseyTest {
+
+ private static final String APPLICATION_NAME = "MyApplication";
+ private static AppEventListener applicationEventListener;
+
+ @Override
+ protected Application configure() {
+ applicationEventListener = new AppEventListener();
+ final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
+ resourceConfig.register(applicationEventListener);
+ resourceConfig.register(RequestFilter.class);
+ resourceConfig.register(PreMatchingRequestFilter.class);
+ resourceConfig.register(ResponseFilter.class);
+ resourceConfig.register(MyExceptionMapper.class);
+ resourceConfig.setApplicationName(APPLICATION_NAME);
+ return resourceConfig;
+ }
+
+ public static class AppEventListener implements ApplicationEventListener {
+ private ApplicationEvent appEventInitStart;
+ private ApplicationEvent appEventInitFinished;
+ private RequestEvent newRequestEvent;
+ private volatile int resourceMethodEventCount = 0;
+ private volatile CountDownLatch finishedCalled = new CountDownLatch(1);
+
+ @Override
+ public void onEvent(ApplicationEvent event) {
+ switch (event.getType()) {
+ case INITIALIZATION_START:
+ this.appEventInitStart = event;
+ break;
+ case INITIALIZATION_APP_FINISHED:
+ this.appEventInitFinished = event;
+ break;
+ }
+ }
+
+ @Override
+ public RequestEventListener onRequest(RequestEvent newRequestEvent) {
+ this.newRequestEvent = newRequestEvent;
+ if ("POST".equals(newRequestEvent.getContainerRequest().getMethod())) {
+ return null;
+ }
+
+ return new ReqEventListener(this);
+ }
+ }
+
+ public static class ReqEventListener implements RequestEventListener {
+ private final AppEventListener appEventListener;
+
+ public final MultivaluedMap<String, String> eventData = new MultivaluedHashMap<String, String>();
+
+ public ReqEventListener(AppEventListener appEventListener) {
+ this.appEventListener = appEventListener;
+ }
+
+ private int index = 1;
+
+ @Override
+ public void onEvent(RequestEvent event) {
+ switch (event.getType()) {
+ case REQUEST_MATCHED:
+ eventData.add("R.REQ_FILTERS_START.order", String.valueOf(index++));
+ break;
+ case REQUEST_FILTERED:
+ eventData.add("R.REQ_FILTERS_FINISHED.order", String.valueOf(index++));
+ break;
+ case LOCATOR_MATCHED:
+ eventData.add("R.MATCHED_LOCATOR.order", String.valueOf(index++));
+ final List<ResourceMethod> locators = event.getUriInfo().getMatchedResourceLocators();
+ String msg = String.valueOf(locators.size())
+ + ":" + locators.get(0).getInvocable().getHandlingMethod().getName();
+ eventData.add("R.MATCHED_LOCATOR", msg);
+ break;
+ case SUBRESOURCE_LOCATED:
+ eventData.add("R.MATCHED_SUB_RESOURCE.order", String.valueOf(index++));
+ break;
+ case RESOURCE_METHOD_START:
+ eventData.add("R.RESOURCE_METHOD_START.order", String.valueOf(index++));
+ this.appEventListener.resourceMethodEventCount++;
+ final ResourceMethod resourceMethod = event.getUriInfo().getMatchedResourceMethod();
+ eventData.add("R.RESOURCE_METHOD_START.method", resourceMethod
+ .getInvocable().getHandlingMethod().getName());
+ break;
+ case RESOURCE_METHOD_FINISHED:
+ eventData.add("R.RESOURCE_METHOD_FINISHED.order", String.valueOf(index++));
+ eventData.add("R.RESOURCE_METHOD_FINISHED", "ok");
+ break;
+ case RESP_FILTERS_START:
+ eventData.add("R.RESP_FILTERS_START.order", String.valueOf(index++));
+ break;
+ case EXCEPTION_MAPPER_FOUND:
+ eventData.add("R.EXCEPTION_MAPPER_FOUND.order", String.valueOf(index++));
+ eventData.add("R.EXCEPTION_MAPPER_FOUND.exception", event.getException().getMessage());
+ break;
+ case RESP_FILTERS_FINISHED:
+ eventData.add("R.RESP_FILTERS_FINISHED.order", String.valueOf(index++));
+ for (Map.Entry<String, List<String>> entry : eventData.entrySet()) {
+ event.getContainerResponse().getHeaders().addAll(entry.getKey(), entry.getValue());
+ }
+ break;
+ case FINISHED:
+ Assert.assertNotNull(event.getContainerResponse());
+ this.appEventListener.finishedCalled.countDown();
+ break;
+ }
+ }
+ }
+
+ public static class MyMappableException extends RuntimeException {
+ public MyMappableException(String message) {
+ super(message);
+ }
+ }
+
+ public static class MyExceptionMapper implements ExceptionMapper<MyMappableException> {
+
+ @Override
+ public Response toResponse(MyMappableException exception) {
+ return Response.ok("mapped").build();
+ }
+ }
+
+ public static class RequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ }
+ }
+
+ @PreMatching
+ public static class PreMatchingRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ }
+ }
+
+
+ public static class ResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ }
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @GET
+ public String getMethod() {
+ return "get";
+ }
+
+ @POST
+ public void post(String entity) {
+ }
+
+ @Path("locator")
+ public SubResource locator() {
+ return new SubResource();
+ }
+
+ @GET
+ @Path("async")
+ @ManagedAsync
+ public void getAsync(@Suspended AsyncResponse asyncResponse) {
+ asyncResponse.resume(Response.ok("async").build());
+ }
+
+ /**
+ * This works in the async way but it is served by only one thread.
+ * @param asyncResponse
+ */
+ @GET
+ @Path("asyncOneThread")
+ public void getAsyncOneThread(@Suspended AsyncResponse asyncResponse) {
+ asyncResponse.resume(Response.ok("async").build());
+ }
+ }
+
+
+ public static class SubResource {
+ @GET
+ public String get() {
+ return "sub";
+ }
+
+ @GET
+ @Path("exception")
+ public String getException() {
+ throw new MyMappableException("test-error");
+ }
+ }
+
+ @Test
+ public void testApplicationEvents() {
+ assertNotNull(applicationEventListener.appEventInitStart);
+ assertNotNull(applicationEventListener.appEventInitFinished);
+ assertEquals(APPLICATION_NAME, applicationEventListener.appEventInitStart.getResourceConfig().getApplicationName());
+ assertNull(applicationEventListener.newRequestEvent);
+ final Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertNotNull(applicationEventListener.newRequestEvent);
+
+ }
+
+ @Test
+ public void testSimpleRequestEvent() {
+ assertEquals(0, applicationEventListener.resourceMethodEventCount);
+ assertNotNull(applicationEventListener.appEventInitStart);
+ assertNull(applicationEventListener.newRequestEvent);
+ Response response = target().path("resource").request().post(Entity.entity("entity",
+ MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(204, response.getStatus());
+ assertNotNull(applicationEventListener.newRequestEvent);
+ assertEquals(0, applicationEventListener.resourceMethodEventCount);
+ response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals(1, applicationEventListener.resourceMethodEventCount);
+ }
+
+ @Test
+ public void testMatchedLocator() {
+ final Response response = target().path("resource/locator").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("sub", response.readEntity(String.class));
+ assertEquals("[1:locator]", response.getHeaderString("R.MATCHED_LOCATOR"));
+ }
+
+ @Test
+ public void testMatchedMethod() {
+ final Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("get", response.readEntity(String.class));
+ assertEquals("[getMethod]", response.getHeaderString("R.RESOURCE_METHOD_START.method"));
+ assertEquals("[ok]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED"));
+ }
+
+ @Test
+ public void testException() {
+ final Response response = target().path("resource/locator/exception").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("mapped", response.readEntity(String.class));
+ assertEquals("[org.glassfish.jersey.tests.e2e.server.monitoring.EventListenerTest$MyMappableException: test-error]",
+ response.getHeaderString("R.EXCEPTION_MAPPER_FOUND.exception"));
+ }
+
+
+ @Test
+ public void testSimpleProcessing() {
+ final Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+
+ assertEquals("get", response.readEntity(String.class));
+
+
+ int i = 1;
+ System.out.println(response.getHeaders());
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order"));
+ assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order"));
+ }
+
+
+ @Test
+ public void testLocatorProcessing() {
+ final Response response = target().path("resource/locator").request().get();
+ assertEquals(200, response.getStatus());
+
+ assertEquals("sub", response.readEntity(String.class));
+
+
+ int i = 1;
+ System.out.println(response.getHeaders());
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_LOCATOR.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_SUB_RESOURCE.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order"));
+ assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order"));
+ }
+
+ @Test
+ public void testExceptionProcessing() {
+ final Response response = target().path("resource/locator/exception").request().get();
+ assertEquals(200, response.getStatus());
+
+ assertEquals("mapped", response.readEntity(String.class));
+
+
+ int i = 1;
+ System.out.println(response.getHeaders());
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_LOCATOR.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_SUB_RESOURCE.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.EXCEPTION_MAPPER_FOUND.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order"));
+ assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order"));
+ }
+
+ @Test
+ public void testAsyncProcessing() throws InterruptedException {
+ final Response response = target().path("resource/async").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("async", response.readEntity(String.class));
+
+ int i = 1;
+ System.out.println(response.getHeaders());
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order"));
+ assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order"));
+ final boolean success = applicationEventListener.finishedCalled.await(3 * getAsyncTimeoutMultiplier(),
+ TimeUnit.SECONDS);
+ Assert.assertTrue(success);
+ }
+
+ @Test
+ public void testAsyncProcessingWithOneThread() throws InterruptedException {
+ final Response response = target().path("resource/asyncOneThread").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("async", response.readEntity(String.class));
+
+ int i = 1;
+ System.out.println(response.getHeaders());
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order"));
+ assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order"));
+ assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order"));
+
+ final boolean success = applicationEventListener.finishedCalled.await(3 * getAsyncTimeoutMultiplier(),
+ TimeUnit.SECONDS);
+ Assert.assertTrue(success);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MBeansTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MBeansTest.java
new file mode 100644
index 0000000..85d0b97
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MBeansTest.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.lang.management.ManagementFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.server.monitoring.MonitoringStatisticsListener;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class MBeansTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(TestResource.class, MyExceptionMapper.class);
+ resourceConfig.setApplicationName("myApplication");
+ resourceConfig.property("very-important", "yes");
+ resourceConfig.property("another-property", 48);
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, true);
+ resourceConfig.register(StatisticsListener.class);
+ return resourceConfig;
+ }
+
+ public static class MyException extends RuntimeException {
+
+ public MyException(String message) {
+ super(message);
+ }
+ }
+
+ public static class MyExceptionMapper implements ExceptionMapper<MyException> {
+
+ @Override
+ public Response toResponse(MyException exception) {
+ return Response.ok("mapped").build();
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @GET
+ public String testGet() {
+ return "get";
+ }
+
+ @GET
+ @Path("test/{test: \\d+}")
+ public String testGetPathPattern1() {
+ return "testGetPathPattern1";
+ }
+
+ @GET
+ @Path("test2/{test: hell?o}")
+ public String testGetPathPattern2() {
+ return "testGetPathPattern2";
+ }
+
+ @GET
+ @Path("test3/{test: abc.* (a)(b)[a,c]?$[1-4]kkx|Y}")
+ public String testGetPathPattern3() {
+ return "testGetPathPattern2";
+ }
+
+ @GET
+ @Path("test4/{test: [a,b]:r}")
+ public String testGetPathPattern4() {
+ return "testGetPathPattern2";
+ }
+
+ @POST
+ public String testPost() {
+ return "post";
+ }
+
+ @GET
+ @Path("sub")
+ public String testSubGet() {
+ return "sub";
+ }
+
+ @GET
+ @Path("exception")
+ public String testException() {
+ throw new MyException("test");
+ }
+
+ @POST
+ @Path("sub2")
+ @Produces("text/html")
+ @Consumes("text/plain")
+ public String testSu2bPost(String entity) {
+ return "post";
+ }
+
+ @Path("locator")
+ public SubResource getSubResource() {
+ return new SubResource();
+ }
+ }
+
+ public static class StatisticsListener extends AbstractContainerLifecycleListener implements MonitoringStatisticsListener {
+
+ public static boolean ON_SHUTDOWN_CALLED = false;
+
+ @Override
+ public void onStatistics(MonitoringStatistics statistics) {
+ // do nothing
+ }
+
+ @Override
+ public void onShutdown(Container container) {
+ StatisticsListener.ON_SHUTDOWN_CALLED = true;
+ }
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ Assert.assertTrue(StatisticsListener.ON_SHUTDOWN_CALLED);
+
+ }
+
+ public static class SubResource {
+
+ @GET
+ @Path("in-subresource")
+ public String get() {
+ return "inSubResource";
+ }
+
+ @Path("locator")
+ public SubResource getSubResource() {
+ return new SubResource();
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ final String path = "resource";
+ assertEquals(200, target().path(path).request().get().getStatus());
+ assertEquals(200, target().path(path).request().post(Entity.entity("post",
+ MediaType.TEXT_PLAIN_TYPE)).getStatus());
+ assertEquals(200, target().path(path).request().post(Entity.entity("post",
+ MediaType.TEXT_PLAIN_TYPE)).getStatus());
+ assertEquals(200, target().path(path).request().post(Entity.entity("post",
+ MediaType.TEXT_PLAIN_TYPE)).getStatus());
+ assertEquals(200, target().path(path).request().post(Entity.entity("post",
+ MediaType.TEXT_PLAIN_TYPE)).getStatus());
+ assertEquals(200, target().path(path + "/sub2").request().post(Entity.entity("post",
+ MediaType.TEXT_PLAIN_TYPE)).getStatus());
+ final Response response = target().path(path + "/exception").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("mapped", response.readEntity(String.class));
+
+ assertEquals(200, target().path("resource/sub").request().get().getStatus());
+ assertEquals(200, target().path("resource/sub").request().get().getStatus());
+ assertEquals(200, target().path("resource/locator/in-subresource").request().get().getStatus());
+ assertEquals(200, target().path("resource/locator/locator/in-subresource").request().get().getStatus());
+ assertEquals(200, target().path("resource/locator/locator/locator/in-subresource").request().get().getStatus());
+ assertEquals(404, target().path("resource/not-found-404").request().get().getStatus());
+
+ // wait until statistics are propagated to mxbeans
+ Thread.sleep(1500);
+
+ final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName("org.glassfish.jersey:type=myApplication,subType=Global,global=Configuration");
+ final String str = (String) mBeanServer.getAttribute(name, "ApplicationName");
+ Assert.assertEquals("myApplication", str);
+
+ checkResourceMBean("/resource");
+ checkResourceMBean("/resource/sub");
+ checkResourceMBean("/resource/locator");
+ checkResourceMBean("/resource/exception");
+ checkResourceMBean("/resource/test/{test: \\\\d+}");
+ checkResourceMBean("/resource/test2/{test: hell\\?o}");
+ checkResourceMBean("/resource/test3/{test: abc.\\* (a)(b)[a,c]\\?$[1-4]kkx|Y}");
+ checkResourceMBean("/resource/test4/{test: [a,b]:r}");
+ }
+
+ private void checkResourceMBean(String name) throws MalformedObjectNameException {
+ final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName objectName = new ObjectName(
+ "org.glassfish.jersey:type=myApplication,subType=Uris,resource=\"" + name + "\"");
+ ObjectInstance mbean = null;
+ try {
+ mbean = mBeanServer.getObjectInstance(objectName);
+ } catch (InstanceNotFoundException e) {
+ Assert.fail("Resource MBean name '" + name + "' not found.");
+ }
+ assertNotNull(mbean);
+ }
+
+ // this test runs the jersey environments, exposes mbeans and makes requests to
+ // the deployed application. The test will never finished. This should be uncommented
+ // only for development testing of mbeans in jconsole.
+ // Steps: uncomment the test; run it; run jconsole and attach to the process of the tests
+ // @Test
+ // public void testNeverFinishesAndMustBeCommented() throws Exception {
+ // while (true) {
+ // test();
+ // }
+ // }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MonitoringStatisticsLocatorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MonitoringStatisticsLocatorTest.java
new file mode 100644
index 0000000..2a4dc66
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/MonitoringStatisticsLocatorTest.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceMethod;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.server.monitoring.ResourceMethodStatistics;
+import org.glassfish.jersey.server.monitoring.ResourceStatistics;
+import org.glassfish.jersey.server.wadl.processor.WadlModelProcessor;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test verifies that {@link ResourceMethodStatistics} are not duplicated in
+ * {@link MonitoringStatistics} when sub resource locators are used. Sub resources and their
+ * methods should be mapped to currently existing {@link ResourceStatistics} and their
+ * {@link ResourceMethodStatistics}.
+ *
+ * @author Miroslav Fuksa
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class MonitoringStatisticsLocatorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(StatisticsResource.class, AnotherResource.class);
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_ENABLED, true);
+ resourceConfig.property(ServerProperties.APPLICATION_NAME, "testApp");
+ return resourceConfig;
+ }
+
+ @Path("resource")
+ public static class StatisticsResource {
+
+ @Context
+ Provider<MonitoringStatistics> statistics;
+
+ @GET
+ public String getStats() throws InterruptedException {
+ final MonitoringStatistics monitoringStatistics = statistics.get();
+ final ResourceStatistics resourceStatistics = monitoringStatistics.getResourceClassStatistics()
+ .get(SubResource.class);
+ if (resourceStatistics == null) {
+ return "null";
+ }
+
+ String resp = "";
+
+ for (final Map.Entry<ResourceMethod, ResourceMethodStatistics> entry
+ : resourceStatistics.getResourceMethodStatistics().entrySet()) {
+ if (entry.getKey().getHttpMethod().equals("GET")) {
+ resp = resp + "getFound";
+ }
+ }
+ return resp;
+ }
+
+ @GET
+ @Path("uri")
+ public String getUriStats() throws InterruptedException {
+ final MonitoringStatistics monitoringStatistics = statistics.get();
+ final ResourceStatistics resourceStatistics = monitoringStatistics.getUriStatistics()
+ .get("/resource/resource-locator");
+ if (resourceStatistics == null) {
+ return "null";
+ }
+
+ String resp = "";
+
+ for (final Map.Entry<ResourceMethod, ResourceMethodStatistics> entry
+ : resourceStatistics.getResourceMethodStatistics().entrySet()) {
+ if (entry.getKey().getHttpMethod().equals("GET")) {
+ resp = resp + "getFound";
+ }
+ }
+
+ return resp;
+ }
+
+ @Path("resource-locator")
+ public SubResource locator() {
+ return new SubResource();
+ }
+
+ @Path("hello")
+ @GET
+ @Produces("text/plain")
+ public String hello() {
+ return "Hello!";
+ }
+
+ @GET
+ @Path("resourceClassStatisticsWadlOptionsTest")
+ public String getResourceClassStatisticsWadlOptionsTest() {
+ return getResourceClassStatisticsTest(WadlModelProcessor.OptionsHandler.class.getName());
+ }
+
+ @GET
+ @Path("resourceClassStatisticsGenericOptionsTest")
+ public String getResourceClassStatisticsGenericOptionsTest() {
+ return getResourceClassStatisticsTest(
+ "org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$GenericOptionsInflector");
+ }
+
+ @GET
+ @Path("resourceClassStatisticsPlainTextOptionsTest")
+ public String getResourceClassStatisticsPlainTestOptionsTest() {
+ return getResourceClassStatisticsTest(
+ "org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$PlainTextOptionsInflector");
+ }
+
+ private String getResourceClassStatisticsTest(final String resourceClassName) {
+ final ResourceStatistics resourceMethodStatistics = findResourceClassStatistics(statistics.get(), resourceClassName);
+
+ boolean resourceHelloOptions = false;
+ boolean anotherHelloOptions = false;
+ boolean anotherXmlOptions = false;
+ for (final Map.Entry<ResourceMethod, ResourceMethodStatistics> entry : resourceMethodStatistics
+ .getResourceMethodStatistics().entrySet()) {
+ final ResourceMethod resourceMethod = entry.getKey();
+ final String fullPath = getFullPath(resourceMethod);
+ if ("/resource/hello".equals(fullPath)) {
+ resourceHelloOptions = true;
+ } else if ("/another/hello".equals(fullPath)) {
+ anotherHelloOptions = true;
+ } else if ("/another/xml".equals(fullPath)) {
+ anotherXmlOptions = true;
+ }
+ }
+ if (resourceHelloOptions && anotherHelloOptions && anotherXmlOptions) {
+ return "OK";
+ } else {
+ return "FAIL: /resource/hello=" + resourceHelloOptions + "; /another/hello=" + anotherHelloOptions
+ + "; /another/xml=" + anotherXmlOptions;
+ }
+ }
+
+ @GET
+ @Path("uriStatisticsResourceHelloTest")
+ public String getUriStatisticsResourceHelloTest() {
+ return getUriStatisticsTest("/resource/hello");
+ }
+
+ @GET
+ @Path("uriStatisticsAnotherHelloTest")
+ public String getUriStatisticsAnotherHelloTest() {
+ return getUriStatisticsTest("/another/hello");
+ }
+
+ @GET
+ @Path("uriStatisticsAnotherXmlTest")
+ public String getUriStatisticsAnotherXmlTest() {
+ return getUriStatisticsTest("/another/xml");
+ }
+
+ private String getUriStatisticsTest(final String uri) {
+ boolean plainTextOptions = false;
+ boolean wadlOptions = false;
+ boolean genericOptions = false;
+ final ResourceStatistics resourceStatistics = statistics.get().getUriStatistics().get(uri);
+
+ for (final Map.Entry<ResourceMethod, ResourceMethodStatistics> entry : resourceStatistics
+ .getResourceMethodStatistics().entrySet()) {
+ if (entry.getKey().getHttpMethod().equals("OPTIONS")) {
+ final ResourceMethod resourceMethod = entry.getKey();
+ final String producedTypes = resourceMethod.getProducedTypes().toString();
+ if ("[text/plain]".equals(producedTypes)) {
+ plainTextOptions = true;
+ } else if ("[application/vnd.sun.wadl+xml]".equals(producedTypes)) {
+ wadlOptions = true;
+ } else if ("[*/*]".equals(producedTypes)) {
+ genericOptions = true;
+ }
+ }
+ }
+ if (plainTextOptions && wadlOptions && genericOptions) {
+ return "OK";
+ } else {
+ return "FAIL: [text/plain]=" + plainTextOptions + "; [application/vnd.sun.wadl+xml]=" + wadlOptions
+ + "; [*/*]=" + genericOptions;
+ }
+ }
+
+ private ResourceStatistics findResourceClassStatistics(final MonitoringStatistics monitoringStatistics,
+ final String resourceClassName) {
+ for (final Map.Entry<Class<?>, ResourceStatistics> entry : monitoringStatistics.getResourceClassStatistics()
+ .entrySet()) {
+ final Class<?> key = entry.getKey();
+ final String clazz = key.getName();
+
+ if (clazz.equals(resourceClassName)) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ private static String getFullPath(final ResourceMethod resourceMethod) {
+ final StringBuilder fullPath = new StringBuilder();
+ if (resourceMethod != null) {
+ prefixPath(fullPath, resourceMethod.getParent());
+ }
+ return fullPath.toString();
+ }
+
+ private static void prefixPath(final StringBuilder fullPath, final Resource parent) {
+ if (parent != null) {
+ String path = parent.getPath();
+ if (path.startsWith("/")) {
+ path = path.substring(1);
+ }
+ fullPath.insert(0, "/" + path);
+ prefixPath(fullPath, parent.getParent());
+ }
+ }
+
+ }
+
+ public static class SubResource {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @Path("sub")
+ public SubResource subLocator() {
+ return new SubResource();
+ }
+
+ }
+
+ @Path("/another")
+ public static class AnotherResource {
+
+ @Path("hello")
+ @GET
+ @Produces("text/plain")
+ public String sayHello() {
+ return "Hello, again.";
+ }
+
+ @Path("xml")
+ @GET
+ @Produces(MediaType.TEXT_XML)
+ public String sayXMLHello() {
+ return "<?xml version=\"1.0\"?><hello>World!</hello>";
+ }
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("null", response.readEntity(String.class));
+
+ response = target().path("resource/resource-locator").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("get", response.readEntity(String.class));
+
+ response = target().path("resource/resource-locator").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("get", response.readEntity(String.class));
+
+ response = target().path("resource/resource-locator/sub").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("get", response.readEntity(String.class));
+
+ response = target().path("resource/hello").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("Hello!", response.readEntity(String.class));
+
+ response = target().path("another/hello").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("Hello, again.", response.readEntity(String.class));
+
+ response = target().path("another/xml").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("<?xml version=\"1.0\"?><hello>World!</hello>", response.readEntity(String.class));
+
+ Thread.sleep(600);
+
+ response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("getFound", response.readEntity(String.class));
+
+ response = target().path("resource/uri").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("getFound", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceClassStatisticsWadlOptions() {
+ final Response response = target().path("resource/resourceClassStatisticsWadlOptionsTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceClassStatisticsGenericOptions() {
+ final Response response = target().path("resource/resourceClassStatisticsGenericOptionsTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceClassStatisticsPlainTextOptions() {
+ final Response response = target().path("resource/resourceClassStatisticsPlainTextOptionsTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testUriStatisticsResourceHello() throws InterruptedException {
+ Response response = target().path("resource/hello").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("Hello!", response.readEntity(String.class));
+
+ Thread.sleep(600);
+
+ response = target().path("resource/uriStatisticsResourceHelloTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testUriStatisticsAnotherHello() throws InterruptedException {
+ Response response = target().path("another/hello").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("Hello, again.", response.readEntity(String.class));
+
+ Thread.sleep(600);
+
+ response = target().path("resource/uriStatisticsAnotherHelloTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testUriStatisticsAnotherXml() throws InterruptedException {
+ Response response = target().path("another/xml").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("<?xml version=\"1.0\"?><hello>World!</hello>", response.readEntity(String.class));
+
+ Thread.sleep(600);
+
+ response = target().path("resource/uriStatisticsAnotherXmlTest").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ReloadApplicationEventTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ReloadApplicationEventTest.java
new file mode 100644
index 0000000..a7a3697
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/ReloadApplicationEventTest.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.lang.management.ManagementFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.ContainerLifecycleListener;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This test tests the lifecycle of the application in accordance to the monitoring
+ * and {@link ContainerLifecycleListener container events}. Among others, it checks that
+ * Monitoring MBeans are correctly exposed and destroyed when application is reloaded. Uses different
+ * containers to test it.
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ReloadApplicationEventTest.GrizzlyTestCase.class, ReloadApplicationEventTest.JdkServerTestCase.class,
+ ReloadApplicationEventTest.SimpleHttpServerTestCase.class})
+public class ReloadApplicationEventTest extends JerseyTest {
+
+ public static final String ORIGINAL = "original";
+ public static final String RELOADED = "reloaded";
+
+ public static class GrizzlyTestCase extends ParentTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+ }
+
+ public static class JdkServerTestCase extends ParentTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JdkHttpServerTestContainerFactory();
+ }
+ }
+
+ /**
+ * Works only with Java 7
+ */
+ public static class JettyServerTestCase extends ParentTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JettyTestContainerFactory();
+ }
+ }
+
+ public static class SimpleHttpServerTestCase extends ParentTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new SimpleTestContainerFactory();
+ }
+ }
+
+ public static class ParentTest extends JerseyTest {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected Application configure() {
+ OriginalResult.reset();
+ ReloadedResult.reset();
+ OriginalResult originalResult = new OriginalResult();
+ final ResourceConfig resourceConfig = getResourceConfig()
+ .setApplicationName(ORIGINAL)
+ .register(new TestResource(originalResult))
+ .register(new AppEventListener(originalResult));
+
+ return resourceConfig;
+ }
+
+ private static ResourceConfig getResourceConfig() {
+ final ResourceConfig resourceConfig = new ResourceConfig();
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, true);
+ return resourceConfig;
+ }
+
+ public static interface TestResultTracker {
+
+ public void reloaded();
+
+ public void shutdown();
+
+ public void startup();
+
+ /**
+ * {@link ApplicationEvent.Type#RELOAD_FINISHED} called.
+ */
+ public void reloadedEvent();
+
+ /**
+ * {@link ApplicationEvent.Type#INITIALIZATION_FINISHED} called.
+ */
+ public void initEvent();
+ }
+
+ public static class OriginalResult implements TestResultTracker {
+
+ public static boolean reloadedCalled;
+ public static boolean shutdownCalled;
+ public static boolean startupCalled;
+ public static boolean reloadedEventCalled;
+ public static boolean initEventCalled;
+
+ public static void reset() {
+ reloadedCalled = false;
+ shutdownCalled = false;
+ startupCalled = false;
+ reloadedEventCalled = false;
+ initEventCalled = false;
+ }
+
+ @Override
+ public void reloaded() {
+ reloadedCalled = true;
+ }
+
+ @Override
+ public void shutdown() {
+ shutdownCalled = true;
+ }
+
+ @Override
+ public void startup() {
+ startupCalled = true;
+ }
+
+ @Override
+ public void reloadedEvent() {
+ reloadedEventCalled = true;
+ }
+
+ @Override
+ public void initEvent() {
+ initEventCalled = true;
+ }
+
+ }
+
+ public static class ReloadedResult implements TestResultTracker {
+
+ public static boolean shutdownCalled;
+ public static boolean reloadedCalled;
+ public static boolean reloadedEventCalled;
+ public static boolean initEventCalled;
+ public static boolean startupCalled;
+
+ public static void reset() {
+ reloadedCalled = false;
+ shutdownCalled = false;
+ startupCalled = false;
+ reloadedEventCalled = false;
+ initEventCalled = false;
+ }
+
+ @Override
+ public void reloaded() {
+ reloadedCalled = true;
+
+ }
+
+ @Override
+ public void shutdown() {
+ shutdownCalled = true;
+ }
+
+ @Override
+ public void startup() {
+ startupCalled = true;
+ }
+
+ @Override
+ public void reloadedEvent() {
+ reloadedEventCalled = true;
+ }
+
+ @Override
+ public void initEvent() {
+ initEventCalled = true;
+ }
+
+ }
+
+ @Path("resource")
+ @Singleton
+ public static class TestResource implements ContainerLifecycleListener {
+
+ private volatile Container container;
+
+ private final TestResultTracker testResultTracker;
+
+ public TestResource(TestResultTracker testResultTracker) {
+ this.testResultTracker = testResultTracker;
+ }
+
+ @GET
+ public String get() {
+ container.reload(getResourceConfig()
+ .setApplicationName(RELOADED)
+ .register(new TestResource(new ReloadedResult()))
+ .register(new AppEventListener(new ReloadedResult())));
+ return "get";
+ }
+
+ @Override
+ public void onStartup(Container container) {
+ this.container = container;
+ testResultTracker.startup();
+ }
+
+ @Override
+ public void onReload(Container container) {
+ testResultTracker.reloaded();
+ }
+
+ @Override
+ public void onShutdown(Container container) {
+ testResultTracker.shutdown();
+ }
+ }
+
+ public static class AppEventListener implements ApplicationEventListener {
+
+ private final TestResultTracker resultTracker;
+
+ public AppEventListener(TestResultTracker resultTracker) {
+ this.resultTracker = resultTracker;
+ }
+
+ @Override
+ public void onEvent(ApplicationEvent event) {
+ switch (event.getType()) {
+ case INITIALIZATION_FINISHED:
+ resultTracker.initEvent();
+ break;
+ case RELOAD_FINISHED:
+ resultTracker.reloadedEvent();
+ break;
+ }
+ }
+
+ @Override
+ public RequestEventListener onRequest(RequestEvent requestEvent) {
+ return null;
+ }
+ }
+
+ /**
+ * Tests that monitoring and container events are correctly called when application is created and redeployed.
+ * It also checks that MBeans are exposed and deregistered when the application is undeployed. Test contains
+ * waits and timeouts as monitoring events are processed asynchronously and it might take some time
+ * until MBeans are registered. The test deploys original application, then reload is initiated and
+ * another application is deployed.
+ *
+ * @throws MalformedObjectNameException
+ * @throws AttributeNotFoundException
+ * @throws MBeanException
+ * @throws ReflectionException
+ * @throws InstanceNotFoundException
+ * @throws InterruptedException
+ */
+ @Test
+ public void testApplicationEvents() throws MalformedObjectNameException, AttributeNotFoundException,
+ MBeanException, ReflectionException, InstanceNotFoundException, InterruptedException {
+ // wait to expose MBeans in the ORIGINAL application
+ Thread.sleep(700);
+
+ // before reload
+ assertTrue(OriginalResult.startupCalled);
+ assertTrue(OriginalResult.initEventCalled);
+ assertFalse(OriginalResult.shutdownCalled);
+
+ assertFalse(ReloadedResult.reloadedCalled);
+ assertFalse(ReloadedResult.startupCalled);
+ assertFalse(ReloadedResult.initEventCalled);
+
+ checkMBeanRegistration(ORIGINAL, true);
+ checkMBeanRegistration(RELOADED, false);
+
+ // now cause the reload:
+ final Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+
+ int cnt = 0;
+ while ((!ReloadedResult.initEventCalled) && (cnt++ < 30)) {
+ Thread.sleep(200);
+ }
+ assertTrue("Timeout: application was not reloaded in time.", ReloadedResult.initEventCalled);
+ // wait again some time until events are processed and mbeans are invoked
+ Thread.sleep(700);
+
+ // after reload
+ assertFalse(OriginalResult.reloadedCalled);
+ assertFalse(OriginalResult.reloadedEventCalled);
+ assertTrue(OriginalResult.shutdownCalled);
+ assertTrue(ReloadedResult.startupCalled);
+ assertTrue(ReloadedResult.initEventCalled);
+ assertTrue(ReloadedResult.reloadedCalled);
+ assertTrue(ReloadedResult.reloadedEventCalled);
+
+ checkMBeanRegistration(ORIGINAL, false);
+ checkMBeanRegistration(RELOADED, true);
+ }
+
+ private void checkMBeanRegistration(String appName, boolean shouldBeRegistered)
+ throws MalformedObjectNameException,
+ MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException,
+ InterruptedException {
+
+ MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName(
+ "org.glassfish.jersey:type=" + appName + ",subType=Global,global=Configuration");
+ boolean registered = mBeanServer.isRegistered(name);
+
+ int time = 0;
+ while (shouldBeRegistered && !registered && time < 4000) {
+ // wait until MBeans are asynchronously exposed
+ int waitTime = 300;
+ time += waitTime;
+ Thread.sleep(waitTime);
+ registered = mBeanServer.isRegistered(name);
+ }
+ Assert.assertEquals(shouldBeRegistered, registered);
+ if (registered) {
+ final String str = (String) mBeanServer.getAttribute(name, "ApplicationName");
+ Assert.assertEquals(appName, str);
+ }
+ }
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/StatisticsDestroyTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/StatisticsDestroyTest.java
new file mode 100644
index 0000000..1fa5d76
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/monitoring/StatisticsDestroyTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.monitoring;
+
+import java.lang.management.ManagementFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.monitoring.DestroyListener;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.server.monitoring.MonitoringStatisticsListener;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({StatisticsDestroyTest.GrizzlyTestCase.class, StatisticsDestroyTest.JdkServerTestCase.class,
+ StatisticsDestroyTest.SimpleHttpServerTestCase.class})
+public class StatisticsDestroyTest {
+
+ public static class ParentTest extends JerseyTest {
+ @Override
+ public Application configure() {
+ StatisticsListener.reset();
+ final ResourceConfig resourceConfig = new ResourceConfig(TestResource.class);
+ resourceConfig.setApplicationName("myApplication");
+ resourceConfig.property("very-important", "yes");
+ resourceConfig.property("another-property", 48);
+ resourceConfig.property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, true);
+ resourceConfig.register(StatisticsListener.class);
+ return resourceConfig;
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ assertTrue(StatisticsListener.ON_SHUTDOWN_CALLED);
+ assertTrue(StatisticsListener.ON_DESTROY_CALLED);
+ assertTrue(StatisticsListener.ON_STATISTICS_CALLED);
+
+ final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName("org.glassfish.jersey:type=myApplication,subType=Global,global=Configuration");
+ boolean registered = mBeanServer.isRegistered(name);
+ int time = 0;
+ while (registered && time < 4000) {
+ // wait until MBeans are asynchronously exposed
+ int waitTime = 300;
+ time += waitTime;
+ Thread.sleep(waitTime);
+ registered = mBeanServer.isRegistered(name);
+ }
+
+ Assert.assertFalse("MBean should be already unregistered!", mBeanServer.isRegistered(name));
+ }
+
+ @Path("resource")
+ public static class TestResource {
+ @GET
+ public String testGet() {
+ return "get";
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ final String path = "resource";
+ assertEquals(200, target().path(path).request().get().getStatus());
+ final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName("org.glassfish.jersey:type=myApplication,subType=Global,global=Configuration");
+ boolean registered = mBeanServer.isRegistered(name);
+
+ // wait (events are processed asynchronously and it might take time to expose mbeans
+ int time = 0;
+ while (!registered && time < 4000) {
+ // wait until MBeans are asynchronously exposed
+ int waitTime = 300;
+ time += waitTime;
+ Thread.sleep(waitTime);
+ registered = mBeanServer.isRegistered(name);
+ }
+
+ assertTrue("MBean should be already registered!", mBeanServer.isRegistered(name));
+ final String str = (String) mBeanServer.getAttribute(name, "ApplicationName");
+ Assert.assertEquals("myApplication", str);
+ }
+ }
+
+ public static class GrizzlyTestCase extends ParentTest {
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ StatisticsListener.reset();
+ return new GrizzlyTestContainerFactory();
+ }
+ }
+
+ public static class JdkServerTestCase extends ParentTest {
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ StatisticsListener.reset();
+ return new JdkHttpServerTestContainerFactory();
+ }
+ }
+
+ /**
+ * Works only with Java 7
+ */
+ public static class JettyServerTestCase extends ParentTest {
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ StatisticsListener.reset();
+ return new JettyTestContainerFactory();
+ }
+ }
+
+ public static class SimpleHttpServerTestCase extends ParentTest {
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ StatisticsListener.reset();
+ return new SimpleTestContainerFactory();
+ }
+ }
+
+ public static class StatisticsListener extends AbstractContainerLifecycleListener
+ implements MonitoringStatisticsListener, DestroyListener {
+
+ public static boolean ON_SHUTDOWN_CALLED = false;
+ public static boolean ON_STATISTICS_CALLED = false;
+ public static boolean ON_DESTROY_CALLED = false;
+
+ public static void reset() {
+ ON_SHUTDOWN_CALLED = false;
+ ON_STATISTICS_CALLED = false;
+ ON_DESTROY_CALLED = false;
+ }
+
+ @Override
+ public void onStatistics(MonitoringStatistics statistics) {
+ StatisticsListener.ON_STATISTICS_CALLED = true;
+ }
+
+ @Override
+ public void onShutdown(Container container) {
+ StatisticsListener.ON_SHUTDOWN_CALLED = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ StatisticsListener.ON_DESTROY_CALLED = true;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest.java
new file mode 100644
index 0000000..9558bb6
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.ErrorTemplate;
+import org.glassfish.jersey.server.mvc.beanvalidation.MvcBeanValidationFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.hibernate.validator.constraints.Length;
+import org.junit.Before;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Michal Gajdos
+ */
+public class BeanValidationErrorTemplateTest extends JerseyTest {
+
+ private Properties props;
+
+ @Before
+ public void setUp() throws Exception {
+ props = new Properties();
+
+ super.setUp();
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ErrorTemplateResource.class)
+ .register(MvcBeanValidationFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Path("/")
+ @Consumes("text/plain")
+ public static class ErrorTemplateResource {
+
+ @POST
+ @Path("params")
+ @ErrorTemplate
+ public String invalidParams(@Length(min = 5) final String value) {
+ fail("Should fail on Bean Validation!");
+ return value;
+ }
+
+ @POST
+ @Path("return")
+ @ErrorTemplate
+ @Length(min = 5)
+ public String invalidReturnValue(final String value) {
+ return value;
+ }
+ }
+
+ @Test
+ public void testInvalidParams() throws Exception {
+ final Response response = target("params").request().post(Entity.text("foo"));
+ props.load(response.readEntity(InputStream.class));
+
+ assertThat(response.getStatus(), equalTo(400));
+ assertThat(props.getProperty("model"),
+ equalTo("{org.hibernate.validator.constraints.Length.message}_ErrorTemplateResource.invalidParams.arg0_foo"));
+ }
+
+ @Test
+ public void testInvalidReturnValue() throws Exception {
+ final Response response = target("return").request().post(Entity.text("foo"));
+ props.load(response.readEntity(InputStream.class));
+
+ assertThat(response.getStatus(), equalTo(500));
+ assertThat(props.getProperty("model"),
+ equalTo("{org.hibernate.validator.constraints.Length.message}_ErrorTemplateResource.invalidReturnValue."
+ + "<return value>_foo"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/CustomViewableContextTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/CustomViewableContextTest.java
new file mode 100644
index 0000000..afcb4d8
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/CustomViewableContextTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.CustomViewableContext;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class CustomViewableContextTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTemplate.class, ImplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class)
+ .register(CustomViewableContext.class);
+ }
+
+ @Path("/explicit")
+ public static class ExplicitTemplate {
+
+ @GET
+ @Template
+ public Viewable getViewable() {
+ return new Viewable("", "method");
+ }
+
+ @GET
+ @Path("annotation")
+ @Template
+ public String getTemplate() {
+ return "annotation";
+ }
+ }
+
+ @Template
+ @Path("/implicit")
+ public static class ImplicitTemplate {
+
+ @Override
+ public String toString() {
+ return "implicit";
+ }
+ }
+
+ @Test
+ public void testExplicitMethod() throws Exception {
+ testResource("explicit", "method");
+ }
+
+ @Test
+ public void testExplicitAnnotation() throws Exception {
+ testResource("explicit/annotation", "annotation");
+ }
+
+ @Test
+ public void testImplicit() throws Exception {
+ testResource("implicit", "implicit");
+ }
+
+ private void testResource(final String path, final String modelValue) throws Exception {
+ final Properties p = new Properties();
+ p.load(target(path).request().get(InputStream.class));
+
+ assertEquals("/CustomViewableContext/index.testp", p.getProperty("path"));
+ assertEquals(modelValue, p.getProperty("model"));
+ assertEquals("TestViewProcessor", p.getProperty("name"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest.java
new file mode 100644
index 0000000..ef8475a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.ErrorTemplate;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ErrorTemplateTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ErrorTemplateResource.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Path("/")
+ public static class ErrorTemplateResource {
+
+ @GET
+ @ErrorTemplate
+ public String method() {
+ throw new RuntimeException("ErrorTemplate");
+ }
+
+ @GET
+ @Path("methodRelativePath")
+ @ErrorTemplate(name = "relative")
+ public String methodRelativePath() {
+ throw new RuntimeException("ErrorTemplate");
+ }
+
+ @GET
+ @Path("methodAbsolutePath")
+ @ErrorTemplate(name = "/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute")
+ public String methodAbsolutePath() {
+ throw new RuntimeException("ErrorTemplate");
+ }
+
+ @Path("subResource")
+ public ErrorTemplateResource subResource() {
+ return new ErrorTemplateResource();
+ }
+
+ @Path("subResourceTemplate")
+ @ErrorTemplate
+ public ErrorTemplateSubResource subResourceTemplate() {
+ return new ErrorTemplateSubResource();
+ }
+ }
+
+ public static class ErrorTemplateSubResource {
+
+ @GET
+ public String get() {
+ throw new RuntimeException("ErrorTemplate");
+ }
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testErrorMethodTemplateSubResource() throws Exception {
+ target("subResourceTemplate").request().get(String.class);
+ }
+
+ @Test
+ public void testErrorTemplate() throws Exception {
+ testErrorTemplate(target());
+ }
+
+ @Test
+ public void testErrorTemplateSubResource() throws Exception {
+ testErrorTemplate(target("subResource"));
+ }
+
+ private void testErrorTemplate(final WebTarget target) throws Exception {
+ Properties props = new Properties();
+ props.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/index.testp",
+ props.getProperty("path"));
+ assertEquals("java.lang.RuntimeException: ErrorTemplate", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodRelativePath").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/relative.testp",
+ props.getProperty("path"));
+ assertEquals("java.lang.RuntimeException: ErrorTemplate", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodAbsolutePath").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.testp",
+ props.getProperty("path"));
+ assertEquals("java.lang.RuntimeException: ErrorTemplate", props.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest.java
new file mode 100644
index 0000000..772c099
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class ExceptionViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class)
+ .register(WebAppExceptionMapper.class);
+ }
+
+ @Provider
+ public static class WebAppExceptionMapper implements ExceptionMapper<WebApplicationException> {
+
+ public Response toResponse(WebApplicationException exception) {
+ // Absolute.
+ if (exception.getResponse().getStatus() == 404) {
+ return Response
+ .status(404)
+ .entity(new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/404", "404"))
+ .build();
+ }
+
+ // Relative.
+ if (exception.getResponse().getStatus() == 406) {
+ return Response.status(406).entity(
+ new Viewable(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/WebAppExceptionMapper/406",
+ "406")).build();
+ }
+
+ return exception.getResponse();
+ }
+ }
+
+ @Path("/")
+ public static class ExplicitTemplate {
+
+ @GET
+ @Produces("application/foo")
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+ }
+
+ @Test
+ public void testAbsoluteExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("/does-not-exist").request();
+
+ Response cr = request.get(Response.class);
+ assertEquals(404, cr.getStatus());
+
+ Properties p = new Properties();
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/404.testp", p.getProperty("path"));
+ assertEquals("404", p.getProperty("model"));
+ }
+
+ @Test
+ public void testResolvingClassExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("/").request("application/wrong-media-type");
+
+ Response cr = request.get(Response.class);
+ assertEquals(406, cr.getStatus());
+
+ Properties p = new Properties();
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/WebAppExceptionMapper/406.testp",
+ p.getProperty("path"));
+ assertEquals("406", p.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest.java
new file mode 100644
index 0000000..95d970b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.AbcViewProcessor;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.DefViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ExplicitProduceTemplateTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTwoGetProducesTemplate.class,
+ ExplicitNoProducesTemplate.class, ExplicitWildcardProducesTemplate.class, ExplicitTemplateProducesClass.class)
+ .register(MvcFeature.class)
+ .register(AbcViewProcessor.class)
+ .register(DefViewProcessor.class);
+ }
+
+ @Path("/explicit-no-produces")
+ public static class ExplicitNoProducesTemplate {
+
+ @GET
+ @Template
+ public String def() {
+ return "def";
+ }
+ }
+
+ @Path("/explicit-wildcard-produces")
+ public static class ExplicitWildcardProducesTemplate {
+
+ @GET
+ @Template
+ @Produces("*/*")
+ public String def() {
+ return "def";
+ }
+ }
+
+ @Path("/explicit-two-get-produces")
+ public static class ExplicitTwoGetProducesTemplate {
+
+ @GET
+ @Template
+ @Produces("application/abc")
+ public String abc() {
+ return "abc";
+ }
+
+ @GET
+ @Template
+ @Produces("*/*")
+ public String def() {
+ return "def";
+ }
+ }
+
+ @Path("explicitTemplateProducesClass")
+ @Produces("application/abc")
+ public static class ExplicitTemplateProducesClass extends ExplicitTemplateTest.ExplicitTemplate {
+ }
+
+ @Test
+ public void testProducesWildcard() throws Exception {
+ for (final String path : new String[] {"explicit-no-produces", "explicit-wildcard-produces",
+ "explicit-two-get-produces"}) {
+ final WebTarget target = target(path);
+
+ for (final String mediaType : new String[] {"application/def", "text/plain"}) {
+ final Properties p = new Properties();
+ p.load(target.request(mediaType).get(InputStream.class));
+
+ assertTrue(p.getProperty("path")
+ .matches("/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/Explicit([a-zA-Z]+)"
+ + "Template/index.def"));
+ assertEquals("def", p.getProperty("model"));
+ assertEquals("DefViewProcessor", p.getProperty("name"));
+ }
+ }
+ }
+
+ @Test
+ public void testProducesSpecific() throws Exception {
+ final WebTarget target = target("explicit-two-get-produces");
+
+ final Properties p = new Properties();
+ p.load(target.request("application/abc").get(InputStream.class));
+
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.abc",
+ p.getProperty("path"));
+ assertEquals("abc", p.getProperty("model"));
+ assertEquals("AbcViewProcessor", p.getProperty("name"));
+ }
+
+ @Test
+ public void testExplicitTemplateProducesClass() throws Exception {
+ final WebTarget target = target("explicitTemplateProducesClass");
+
+ Properties props = new Properties();
+ props.load(target.request().get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/index.abc",
+ props.getProperty("path"));
+ assertEquals("method", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodRelativePath").request().get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/relative"
+ + ".abc",
+ props.getProperty("path"));
+ assertEquals("methodRelativePath", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodAbsolutePath").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.abc",
+ props.getProperty("path"));
+ assertEquals("methodAbsolutePath", props.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest.java
new file mode 100644
index 0000000..0bbd8b5
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ExplicitTemplateTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ public static class CustomResolvingClass {
+ }
+
+ @Path("/")
+ public static class ExplicitTemplate {
+
+ @GET
+ @Template
+ public String method() {
+ return "method";
+ }
+
+ @GET
+ @Path("methodRelativePath")
+ @Template(name = "relative")
+ public String methodRelativePath() {
+ return "methodRelativePath";
+ }
+
+ @GET
+ @Path("methodAbsolutePath")
+ @Template(name = "/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute")
+ public String methodAbsolutePath() {
+ return "methodAbsolutePath";
+ }
+
+ @Path("subResource")
+ public ExplicitTemplate subResource() {
+ return new ExplicitTemplate();
+ }
+
+ @Path("subResourceTemplate")
+ @Template
+ public ExplicitTemplateSubResource subResourceTemplate() {
+ return new ExplicitTemplateSubResource();
+ }
+ }
+
+ public static class ExplicitTemplateSubResource {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Test
+ public void testExplicitMethodTemplateSubResource() throws Exception {
+ assertEquals("get", target("subResourceTemplate").request().get(String.class));
+ }
+
+ @Test
+ public void testExplicitTemplate() throws Exception {
+ _testExplicitTemplate(target());
+ }
+
+ @Test
+ public void testExplicitTemplateSubResource() throws Exception {
+ _testExplicitTemplate(target("subResource"));
+ }
+
+ void _testExplicitTemplate(final WebTarget target) throws Exception {
+ Properties props = new Properties();
+ props.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/index.testp",
+ props.getProperty("path"));
+ assertEquals("method", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodRelativePath").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/relative.testp",
+ props.getProperty("path"));
+ assertEquals("methodRelativePath", props.getProperty("model"));
+
+ props = new Properties();
+ props.load(target.path("methodAbsolutePath").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.testp",
+ props.getProperty("path"));
+ assertEquals("methodAbsolutePath", props.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.java
new file mode 100644
index 0000000..b3c0dce
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class FlatInheritedViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTemplate.class, ImplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ public static class ExplicitTemplateBase {
+ }
+
+ @Path("/explicit")
+ public static class ExplicitTemplate extends ExplicitTemplateBase {
+
+ @GET
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+
+ @Path("inherit")
+ @GET
+ public Viewable getInherited() {
+ return new Viewable("inherit", "get");
+ }
+
+ @Path("override")
+ @GET
+ public Viewable getOverriden() {
+ return new Viewable("override", "get");
+ }
+ }
+
+ @Test
+ public void testExplicitTemplate() throws IOException {
+ final WebTarget target = target("explicit");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("inherit").request().get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.inherit.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("override").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplate.override.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+ }
+
+ public static class ImplicitTemplateBase {
+ }
+
+ @Path("/implicit")
+ @Template
+ public static class ImplicitTemplate extends ImplicitTemplateBase {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final WebTarget target = target("implicit");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("inherit").request().get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.inherit.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("override").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplate.override.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.java
new file mode 100644
index 0000000..72a1f39
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class FlatViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ExplicitTemplate.class, ImplicitTemplate.class, ImplicitExplicitTemplate.class,
+ ImplicitWithGetTemplate.class, ImplicitWithSubResourceGetTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Path("/explicit")
+ public static class ExplicitTemplate {
+
+ @GET
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+
+ @POST
+ public Viewable post() {
+ return new Viewable("show", "post");
+ }
+ }
+
+ @Test
+ public void testExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("explicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ExplicitTemplate.show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(request.post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE), InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ExplicitTemplate.show.testp",
+ p.getProperty("path"));
+ assertEquals("post", p.getProperty("model"));
+ }
+
+ @Path("/implicit")
+ @Template
+ public static class ImplicitTemplate {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("implicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitTemplate.index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+
+ @Path("/implicit-explicit")
+ @Template
+ public static class ImplicitExplicitTemplate {
+
+ public String toString() {
+ return "ImplicitExplicitTemplate";
+ }
+
+ @POST
+ public Viewable post() {
+ return new Viewable("show", "post");
+ }
+
+ @Path("sub")
+ @GET
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+ }
+
+ @Test
+ public void testImplicitExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("implicit-explicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitExplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(request.post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE), InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.show.testp",
+ p.getProperty("path"));
+ assertEquals("post", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target("implicit-explicit").path("sub").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+ }
+
+ @Path("/implicit-get")
+ @Template
+ public static class ImplicitWithGetTemplate {
+
+ @GET
+ @Produces("application/foo")
+ public String toString() {
+ return "ImplicitWithGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get");
+
+ Properties p = new Properties();
+ p.load(target.request("text/plain").get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithGetTemplate.index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ assertEquals("ImplicitWithGetTemplate", target.request("application/foo").get(String.class));
+ }
+
+ @Path("/implicit-get-subresource")
+ @Template
+ public static class ImplicitWithSubResourceGetTemplate {
+
+ @Path("sub")
+ @GET
+ @Produces("application/foo")
+ public String toString() {
+ return "ImplicitWithSubResourceGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithSubResourceGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get-subresource").path("sub");
+
+ Properties p = new Properties();
+ p.load(target.request("text/plain").get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithSubResourceGetTemplate.sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ assertEquals("ImplicitWithSubResourceGetTemplate", target.request("application/foo").get(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest.java
new file mode 100644
index 0000000..bd705f0
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class ImplicitProducesViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(
+ ImplicitTemplate.class,
+ ImplicitWithGetTemplate.class,
+ ImplicitWithSubResourceGetTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class).property("jersey.config.server.tracing", "ALL");
+ }
+
+ @Path("/implicit")
+ @Template
+ @Produces("text/plain;qs=.5")
+ public static class ImplicitTemplate {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final WebTarget target = target("implicit");
+
+ Properties p = new Properties();
+ Response cr = target.request("text/plain", "application/foo").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo", "text/plain").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("text/plain;q=0.5", "application/foo").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo", "text/plain;q=0.5").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+
+ @Path("/implicit-get")
+ @Template
+ @Produces("text/plain;qs=0.5")
+ public static class ImplicitWithGetTemplate {
+
+ @GET
+ @Produces("application/foo;qs=0.2")
+ public String toString() {
+ return "ImplicitWithGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get");
+
+ Properties p = new Properties();
+ Response cr = target.request("text/plain", "application/foo").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index"
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo", "text/plain").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index"
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("text/plain", "application/foo;q=0.5").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index"
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo;q=0.5", "text/plain").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index"
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("*/*").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index"
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ cr = target.request("text/plain;q=0.5", "application/foo").get(Response.class);
+ assertEquals(new MediaType("application", "foo"), cr.getMediaType());
+ assertEquals("ImplicitWithGetTemplate", cr.readEntity(String.class));
+ }
+
+ @Path("/implicit-get-subresource")
+ @Template
+ @Produces("text/plain;qs=0.5")
+ public static class ImplicitWithSubResourceGetTemplate {
+
+ @GET
+ @Path("sub")
+ @Produces("application/foo;qs=0.2")
+ public String toString() {
+ return "ImplicitWithSubResourceGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithSubResourceGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get-subresource").path("sub");
+
+ Properties p = new Properties();
+ Response cr = target.request("text/plain", "application/foo").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest"
+ + "/ImplicitWithSubResourceGetTemplate/sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo", "text/plain").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest"
+ + "/ImplicitWithSubResourceGetTemplate/sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("text/plain", "application/foo;q=0.5").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest"
+ + "/ImplicitWithSubResourceGetTemplate/sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ cr = target.request("application/foo;q=0.5", "text/plain").get(Response.class);
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, cr.getMediaType());
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest"
+ + "/ImplicitWithSubResourceGetTemplate/sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ assertEquals("ImplicitWithSubResourceGetTemplate", target.request("application/foo").get(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest.java
new file mode 100644
index 0000000..0de3486
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ImplicitTemplateProgrammaticTest extends JerseyTest {
+
+ @Template
+ public static class Handler {
+
+ private String constructor = "no-arg";
+
+ @SuppressWarnings("UnusedDeclaration")
+ public Handler() {
+ }
+
+ public Handler(final String constructor) {
+ this.constructor = constructor;
+ }
+
+ @Override
+ public String toString() {
+ return "Resource_" + constructor;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ Method toStringMethod = null;
+
+ try {
+ toStringMethod = Handler.class.getMethod("toString");
+ } catch (NoSuchMethodException e) {
+ // Eat that.
+ }
+
+ final Resource.Builder resourceBuilder = Resource.builder("implicit");
+
+ resourceBuilder.addMethod(HttpMethod.POST).consumes("application/foo").handledBy(Handler.class, toStringMethod);
+ resourceBuilder.addMethod(HttpMethod.POST).consumes("application/bar").handledBy(new Handler("arg"), toStringMethod);
+
+ return new ResourceConfig()
+ .registerResources(resourceBuilder.build())
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Test
+ public void testImplicitHandlerClass() throws Exception {
+ Properties p = new Properties();
+ p.load(target("implicit").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest/Handler/index.testp",
+ p.getProperty("path"));
+ assertEquals("Resource_no-arg", p.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest.java
new file mode 100644
index 0000000..7fb0ba8
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ImplicitTemplateTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(
+ ImplicitResource.class, AnotherImplicitResource.class,
+ ImplicitSingletonResource.class, ImplicitRootResource.class,
+ ImplicitGetResource.class, AnotherImplicitGetResource.class, AnotherAnotherImplicitGetResource.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Template
+ @Path("/implicit")
+ public static class ImplicitResource {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Path("/implicit")
+ public static class AnotherImplicitResource {
+
+ public String toString() {
+ return "ImplicitAnotherTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplateResources() throws Exception {
+ for (final String path : new String[] {"", "index", "get"}) {
+ WebTarget target = target("implicit");
+ String templateName = "index";
+
+ if (!"".equals(path)) {
+ templateName = path;
+ target = target.path(path);
+ }
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/" + templateName + ".testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+ }
+
+ @Test
+ public void testImplicitTemplateResourcesNegative() throws Exception {
+ assertEquals(404, target("implicit").path("do-not-exist").request().get().getStatus());
+ }
+
+ @Path("/implicit-get")
+ @Produces("text/html")
+ public static class ImplicitGetResource {
+
+ @GET
+ public String get() {
+ return toString();
+ }
+
+ public String toString() {
+ return "ImplicitGetTemplate";
+ }
+ }
+
+ @Path("/implicit-get")
+ @Template
+ @Produces("text/plain")
+ public static class AnotherImplicitGetResource {
+
+ @GET
+ @Path("sub")
+ public String get() {
+ return toString();
+ }
+
+ public String toString() {
+ return "AnotherImplicitGetTemplate";
+ }
+ }
+
+ @Path("/implicit-get/another")
+ public static class AnotherAnotherImplicitGetResource {
+
+ @GET
+ public String get() {
+ return toString();
+ }
+
+ public String toString() {
+ return "AnotherAnotherImplicitGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitGetTemplateResources() throws Exception {
+ for (final String path : new String[] {"", "index", "get"}) {
+ WebTarget target = target("implicit-get");
+ String templateName = "index";
+
+ if (!"".equals(path)) {
+ templateName = path;
+ target = target.path(path);
+ }
+
+ Properties p = new Properties();
+ p.load(target.request("text/plain").get(InputStream.class));
+ assertEquals(
+ "/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/" + templateName
+ + ".testp",
+ p.getProperty("path"));
+ assertEquals("AnotherImplicitGetTemplate", p.getProperty("model"));
+ }
+ }
+
+ @Template
+ @Singleton
+ @Path("/implicit-singleton")
+ public static class ImplicitSingletonResource {
+
+ private int counter = 0;
+
+ public String toString() {
+ return "ImplicitSingletonTemplate" + counter++;
+ }
+ }
+
+ @Test
+ public void testImplicitTemplateSingletonResources() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ final WebTarget target = target("implicit-singleton");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSingletonResource/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitSingletonTemplate" + i, p.getProperty("model"));
+ }
+ }
+
+ @Path("/implicit-sub-resource")
+ public static class ImplicitRootResource {
+
+ @Path("sub")
+ public ImplicitSubResource getSubResource() {
+ return new ImplicitSubResource("ImplicitRootResource");
+ }
+ }
+
+ public static class ImplicitSubResource {
+
+ private final String string;
+
+ public ImplicitSubResource(final String string) {
+ this.string = string;
+ }
+
+ @Path("sub")
+ public ImplicitSubSubResource getSubResource() {
+ return new ImplicitSubSubResource(string + "ImplicitSubResource");
+ }
+ }
+
+ @Template
+ public static class ImplicitSubSubResource {
+
+ private final String string;
+
+ public ImplicitSubSubResource(final String string) {
+ this.string = string;
+ }
+
+ @Override
+ public String toString() {
+ return string + "ImplicitSubSubResource";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplateSubResources() throws Exception {
+ final WebTarget target = target("implicit-sub-resource").path("sub").path("sub");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSubSubResource/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitRootResourceImplicitSubResourceImplicitSubSubResource", p.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest.java
new file mode 100644
index 0000000..4d81576
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Properties;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class ImplicitViewWithResourceFilterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(ImplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(FilterOne.class)
+ .register(FilterTwo.class)
+ .register(TestViewProcessor.class);
+ }
+
+ @Path("/")
+ @Template
+ public static class ImplicitTemplate {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Priority(10)
+ public static class FilterOne implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ List<String> xTest = requestContext.getHeaders().get("X-TEST");
+ assertNull(xTest);
+
+ requestContext.getHeaders().add("X-TEST", "one");
+ }
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws
+ IOException {
+ List<String> rxTest = requestContext.getHeaders().get("X-TEST");
+ assertEquals(2, rxTest.size());
+ assertEquals("one", rxTest.get(0));
+ assertEquals("two", rxTest.get(1));
+
+ List<Object> xTest = responseContext.getHeaders().get("X-TEST");
+ assertEquals(1, xTest.size());
+ assertEquals("two", xTest.get(0));
+
+ assertNull(responseContext.getHeaders().get("Y-TEST"));
+ responseContext.getHeaders().add("Y-TEST", "one");
+ }
+ }
+
+ @Priority(20)
+ public static class FilterTwo implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ List<String> xTest = requestContext.getHeaders().get("X-TEST");
+ assertEquals(1, xTest.size());
+ assertEquals("one", xTest.get(0));
+
+ requestContext.getHeaders().add("X-TEST", "two");
+ }
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws
+ IOException {
+ List<String> rxTest = requestContext.getHeaders().get("X-TEST");
+ assertEquals(2, rxTest.size());
+ assertEquals("one", rxTest.get(0));
+ assertEquals("two", rxTest.get(1));
+
+ assertNull(responseContext.getHeaders().get("X-TEST"));
+ assertNull(responseContext.getHeaders().get("Y-TEST"));
+
+ responseContext.getHeaders().add("X-TEST", "two");
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("/").request();
+
+ Response cr = request.get(Response.class);
+ assertEquals(200, cr.getStatus());
+ List<Object> xTest = cr.getMetadata().get("X-TEST");
+ assertEquals(1, xTest.size());
+ assertEquals("two", xTest.get(0));
+
+ List<Object> yTest = cr.getMetadata().get("Y-TEST");
+ assertEquals(1, yTest.size());
+ assertEquals("one", yTest.get(0));
+
+ Properties p = new Properties();
+ p.load(cr.readEntity(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest.java
new file mode 100644
index 0000000..88d847a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class InheritedViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(
+ ExplicitTemplate.class,
+ ImplicitTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ }
+
+ public static class ExplicitTemplateBase {
+ }
+
+ @Path("/explicit")
+ public static class ExplicitTemplate extends ExplicitTemplateBase {
+
+ @GET
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+
+ @Path("inherit")
+ @GET
+ public Viewable getInherited() {
+ return new Viewable("inherit", "get");
+ }
+
+ @Path("override")
+ @GET
+ public Viewable getOverriden() {
+ return new Viewable("override", "get");
+ }
+ }
+
+ @Test
+ public void testExplicitTemplate() throws IOException {
+ final WebTarget target = target("explicit");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("inherit").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/inherit.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("override").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplate/override.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+ }
+
+ public static class ImplicitTemplateBase {
+ }
+
+ @Path("/implicit")
+ @Template
+ public static class ImplicitTemplate extends ImplicitTemplateBase {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final WebTarget target = target("implicit");
+
+ Properties p = new Properties();
+ p.load(target.request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("inherit").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/inherit.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target.path("override").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplate/override.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest.java
new file mode 100644
index 0000000..68ad121
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
+import org.glassfish.jersey.server.mvc.mustache.MustacheMvcFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * MVC encoding charset tests.
+ *
+ * @author Miroslav Fuksa
+ */
+@RunWith(Parameterized.class)
+public class MvcEncodingTest extends JerseyTest {
+
+ public static final String MESSAGE = "\\u0161\\u010d\\u0159\\u017e\\u00fd\\u00e1\\u00ed\\u00e9";
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {new FreemarkerMvcFeature(), "freemarker", "FreemarkerResource.ftl", "UTF-8"},
+ {new FreemarkerMvcFeature(), "freemarker", "FreemarkerResource.ftl", "UTF-16"},
+ {new FreemarkerMvcFeature(), "freemarker", "FreemarkerResource.ftl", "windows-1250"},
+ {new FreemarkerMvcFeature(), "freemarker", "FreemarkerResource.ftl", "ISO-8859-2"},
+ {new MustacheMvcFeature(), "mustache", "MustacheResource.mustache", "UTF-8"},
+ {new MustacheMvcFeature(), "mustache", "MustacheResource.mustache", "UTF-16"},
+ {new MustacheMvcFeature(), "mustache", "MustacheResource.mustache", "windows-1250"},
+ {new MustacheMvcFeature(), "mustache", "MustacheResource.mustache", "ISO-8859-2"},
+ });
+ }
+
+ private static String templateName;
+ private final String defaultEncoding;
+
+ public MvcEncodingTest(Feature feature, String propertySuffix, String templateName, String defaultEncoding) {
+ super(new ResourceConfig()
+ .register(feature)
+ .register(FreemarkerResource.class)
+ .property(MvcFeature.ENCODING + "." + propertySuffix, defaultEncoding));
+ MvcEncodingTest.templateName = templateName;
+ this.defaultEncoding = defaultEncoding;
+ }
+
+
+ @Path("resource")
+ public static class FreemarkerResource {
+ @GET
+ public Viewable get() {
+ final Map<String, String> map = new HashMap<String, String>();
+ map.put("user", MESSAGE);
+
+ return new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/" + templateName, map);
+ }
+
+ @GET
+ @Path("textplain")
+ @Produces("text/plain")
+ public Viewable getTextPlain() {
+ final Map<String, String> map = new HashMap<String, String>();
+ map.put("user", MESSAGE);
+
+ return new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/" + templateName, map);
+ }
+
+ @GET
+ @Path("textplainUTF16")
+ @Produces("text/plain;charset=UTF-16")
+ public Viewable getTextPlainUTF16() {
+ final Map<String, String> map = new HashMap<String, String>();
+ map.put("user", MESSAGE);
+
+ return new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/" + templateName, map);
+ }
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ @Test
+ public void testDefaultEncoding() {
+ final Response response = target().path("resource").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("Model:" + MESSAGE, response.readEntity(String.class));
+ Assert.assertEquals("*/*;charset=" + defaultEncoding, response.getMediaType().toString());
+ Assert.assertEquals(defaultEncoding, response.getMediaType().getParameters().get(MediaType.CHARSET_PARAMETER));
+ }
+
+ @Test
+ public void testTextPlainDefaultEncoding() {
+ final Response response = target().path("resource/textplain").request("*/*,text/plain,text/html").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("Model:" + MESSAGE, response.readEntity(String.class));
+ Assert.assertEquals("text/plain;charset=" + defaultEncoding, response.getMediaType().toString());
+ Assert.assertEquals(defaultEncoding, response.getMediaType().getParameters().get(MediaType.CHARSET_PARAMETER));
+ }
+
+ @Test
+ public void testTextPlain406() {
+ final Response response = target().path("resource/textplain").request("text/html").get();
+ Assert.assertEquals(406, response.getStatus());
+ }
+
+ @Test
+ public void testTextPlainUTF16() {
+ final Response response = target().path("resource/textplainUTF16").request("*/*,text/plain,text/html").get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("Model:" + MESSAGE, response.readEntity(String.class));
+ Assert.assertEquals("text/plain;charset=UTF-16", response.getMediaType().toString());
+ Assert.assertEquals("UTF-16", response.getMediaType().getParameters().get(MediaType.CHARSET_PARAMETER));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest.java
new file mode 100644
index 0000000..39d3f77
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests that {@link Template} annotated methods are selected by the routing algorithms as if they
+ * would actually return {@link Viewable} instead of the model.
+ *
+ * @author Miroslav Fuksa
+ */
+public class TemplateMethodSelectionTest extends JerseyTest {
+
+ private static final Map<String, String> MODEL = new HashMap<String, String>() {{
+ put("a", "hello");
+ put("b", "world");
+ }};
+
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ TemplateAnnotatedResourceMethod.class,
+ TemplateAnnotatedResource.class,
+ BasicResource.class,
+ AsViewableResource.class,
+ NoTemplateResource.class,
+ LoggingFeature.class,
+ MvcFeature.class,
+ TestViewProcessor.class,
+ MoxyJsonFeature.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(MoxyJsonFeature.class);
+ }
+
+ public static MyBean getMyBean() {
+ final MyBean myBean = new MyBean();
+ myBean.setName("hello");
+ return myBean;
+ }
+
+ @XmlRootElement
+ public static class MyBean {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+ }
+
+ @Path("annotatedMethod")
+ public static class TemplateAnnotatedResourceMethod {
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ @Template()
+ public Map<String, String> getAsHTML() {
+ return MODEL;
+ }
+
+ @GET
+ @Produces("application/json")
+ public MyBean getAsJSON() {
+ return getMyBean();
+ }
+ }
+
+ @Path("noTemplate")
+ public static class NoTemplateResource {
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Map<String, String> getAsHTML() {
+ return MODEL;
+ }
+
+ @GET
+ @Produces("application/json")
+ public MyBean getAsJSON() {
+ return getMyBean();
+ }
+ }
+
+ @Path("annotatedClass")
+ @Template
+ @Produces(MediaType.TEXT_HTML)
+ public static class TemplateAnnotatedResource {
+
+ @GET
+ @Produces("application/json")
+ public MyBean getAsJSON() {
+ return getMyBean();
+ }
+
+ @Override
+ public String toString() {
+ return "This toString() method will be used to get model.";
+ }
+ }
+
+ @Path("basic")
+ public static class BasicResource {
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public String getAsHTML() {
+ return "Hello World";
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public MyBean getAsJSON() {
+ return getMyBean();
+ }
+ }
+
+ @Path("viewable")
+ public static class AsViewableResource {
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getAsHTML() {
+ return new Viewable("index.testp", MODEL);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public MyBean getAsJSON() {
+ return getMyBean();
+ }
+ }
+
+ /**
+ * This test makes request for text/html which is preferred. The resource defines the method
+ * {@link org.glassfish.jersey.tests.e2e.server.mvc.TemplateMethodSelectionTest.TemplateAnnotatedResourceMethod#getAsHTML()}
+ * which returns {@link Map} for which there is not {@link javax.ws.rs.ext.MessageBodyWriter}. The absence of the
+ * writer would cause that the method would not have been selected but as the {@link Template} annotation
+ * is on the method, the {@link org.glassfish.jersey.server.internal.routing.MethodSelectingRouter} considers
+ * it as if this would have been {@link Viewable} instead of the {@link Map}.
+ */
+ @Test
+ public void testAnnotatedMethodByTemplateHtml() {
+ final Response response = target().path("annotatedMethod").request("text/html;q=0.8", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_HTML_TYPE, response.getMediaType());
+ assertThat(response.readEntity(String.class),
+ anyOf(containsString("{b=world, a=hello}"), containsString("{a=hello, b=world}")));
+ }
+
+ @Test
+ public void testAnnotatedMethodByTemplateJson() {
+ final Response response = target().path("annotatedMethod").request("text/html;q=0.6", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+ @Test
+ public void testAnnotatedClassByTemplateHtml() {
+ final Response response = target().path("annotatedClass").request("text/html;q=0.8", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_HTML_TYPE, response.getMediaType());
+ assertTrue(response.readEntity(String.class).contains("model=This toString() method will be used to get model."));
+ }
+
+ @Test
+ public void testAnnotatedClassByTemplateJson() {
+ final Response response = target().path("annotatedClass").request("text/html;q=0.6", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+ @Test
+ public void testBasicHtml() {
+ final Response response = target().path("basic").request("text/html;q=0.8", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_HTML_TYPE, response.getMediaType());
+ assertTrue(response.readEntity(String.class).contains("Hello World"));
+ }
+
+ @Test
+ public void testBasicJson() {
+ final Response response = target().path("basic").request("text/html;q=0.6", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+ @Test
+ public void testAsViewableHtml() {
+ final Response response = target().path("viewable").request("text/html;q=0.8", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_HTML_TYPE, response.getMediaType());
+ assertThat(response.readEntity(String.class),
+ anyOf(containsString("{b=world, a=hello}"), containsString("{a=hello, b=world}")));
+ }
+
+ @Test
+ public void testAsViewableJson() {
+ final Response response = target().path("viewable").request("text/html;q=0.6", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+ /**
+ * This test verifies that there is really no {@link javax.ws.rs.ext.MessageBodyWriter}
+ * for {@code Map<String,String>}}. text/html is requested but application/json is chosen there is no
+ * MBW for {@code Map}.
+ */
+ @Test
+ public void testNoTemplateHtml() {
+ final Response response = target().path("noTemplate").request("text/html;q=0.9", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+ @Test
+ public void testNoTemplateJson() {
+ final Response response = target().path("noTemplate").request("text/html;q=0.6", "application/json;q=0.7").get();
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ assertEquals("hello", response.readEntity(MyBean.class).getName());
+ }
+
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest.java
new file mode 100644
index 0000000..15be3f6
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.e2e.server.mvc.provider.TestViewProcessor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class ViewProcessorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ ResourceConfig register = new ResourceConfig(
+ ExplicitTemplate.class,
+ ImplicitTemplate.class,
+ ImplicitExplicitTemplate.class,
+ ImplicitWithGetTemplate.class,
+ ImplicitWithSubResourceGetTemplate.class)
+ .register(MvcFeature.class)
+ .register(TestViewProcessor.class);
+ register.property(ServerProperties.WADL_FEATURE_DISABLE, true);
+ return register;
+ }
+
+ @Template
+ @Path("/explicit")
+ public static class ExplicitTemplate {
+
+ @GET
+ @Template
+ public Response get() {
+ return Response.ok().entity(new Viewable("show", "get")).build();
+ }
+
+ @POST
+ public Viewable post() {
+ return new Viewable("show", "post");
+ }
+
+ @GET
+ @Path("absolute")
+ public Viewable getAbs() {
+ return new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show",
+ "get");
+ }
+
+ @POST
+ @Path("absolute")
+ public Viewable postAbs() {
+ return new Viewable("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show",
+ "post");
+ }
+ }
+
+ @Test
+ public void testExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("explicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(request.post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE), InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/show.testp",
+ p.getProperty("path"));
+ assertEquals("post", p.getProperty("model"));
+ }
+
+ @Test
+ public void testExplicitAbsoluteTemplate() throws IOException {
+ final Invocation.Builder request = target("explicit").path("absolute").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(request.post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE), InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show.testp",
+ p.getProperty("path"));
+ assertEquals("post", p.getProperty("model"));
+ }
+
+ @Path("/implicit")
+ @Template
+ public static class ImplicitTemplate {
+
+ public String toString() {
+ return "ImplicitTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("implicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitTemplate", p.getProperty("model"));
+ }
+
+ @Path("/implicit-explicit")
+ @Template
+ public static class ImplicitExplicitTemplate {
+
+ public String toString() {
+ return "ImplicitExplicitTemplate";
+ }
+
+ @POST
+ public Viewable post() {
+ return new Viewable("show", "post");
+ }
+
+ @GET
+ @Path("sub")
+ public Viewable get() {
+ return new Viewable("show", "get");
+ }
+ }
+
+ @Test
+ public void testImplicitExplicitTemplate() throws IOException {
+ final Invocation.Builder request = target("implicit-explicit").request();
+
+ Properties p = new Properties();
+ p.load(request.get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitExplicitTemplate", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(request.post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE), InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/show.testp",
+ p.getProperty("path"));
+ assertEquals("post", p.getProperty("model"));
+
+ p = new Properties();
+ p.load(target("implicit-explicit").path("sub").request().get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/show.testp",
+ p.getProperty("path"));
+ assertEquals("get", p.getProperty("model"));
+ }
+
+ @Path("/implicit-get")
+ @Template
+ public static class ImplicitWithGetTemplate {
+
+ @GET
+ @Produces("application/foo")
+ public String toString() {
+ return "ImplicitWithGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get");
+
+ Properties p = new Properties();
+ p.load(target.request("text/plain").get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithGetTemplate/index.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithGetTemplate", p.getProperty("model"));
+
+ assertEquals("ImplicitWithGetTemplate", target.request("application/foo").get(String.class));
+ }
+
+ @Path("/implicit-get-subresource")
+ @Template
+ public static class ImplicitWithSubResourceGetTemplate {
+
+ @GET
+ @Path("sub")
+ @Produces("application/foo")
+ public String toString() {
+ return "ImplicitWithSubResourceGetTemplate";
+ }
+ }
+
+ @Test
+ public void testImplicitWithSubResourceGetTemplate() throws IOException {
+ final WebTarget target = target("implicit-get-subresource").path("sub");
+
+ Properties p = new Properties();
+ p.load(target.request("text/plain").get(InputStream.class));
+ assertEquals("/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp",
+ p.getProperty("path"));
+ assertEquals("ImplicitWithSubResourceGetTemplate", p.getProperty("model"));
+
+ assertEquals("ImplicitWithSubResourceGetTemplate", target.request("application/foo").get(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/AbcViewProcessor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/AbcViewProcessor.java
new file mode 100644
index 0000000..07772c6
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/AbcViewProcessor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc.provider;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Michal Gajdos
+ */
+public class AbcViewProcessor extends TestViewProcessor {
+
+ @Override
+ protected String getExtension() {
+ return ".abc";
+ }
+
+ @Override
+ protected String getViewProcessorName() {
+ return "AbcViewProcessor";
+ }
+
+ @Override
+ protected boolean acceptMediaType(final MediaType mediaType) {
+ return new MediaType("application", "abc").equals(mediaType);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/CustomViewableContext.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/CustomViewableContext.java
new file mode 100644
index 0000000..edbd8f3
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/CustomViewableContext.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc.provider;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.server.mvc.internal.TemplateHelper;
+import org.glassfish.jersey.server.mvc.spi.ResolvedViewable;
+import org.glassfish.jersey.server.mvc.spi.TemplateProcessor;
+import org.glassfish.jersey.server.mvc.spi.ViewableContext;
+
+/**
+ * Custom {@link ViewableContext viewable context}.
+ *
+ * @author Michal Gajdos
+ */
+@Provider
+public class CustomViewableContext implements ViewableContext {
+
+ @Override
+ public ResolvedViewable resolveViewable(final Viewable viewable, final MediaType mediaType,
+ final Class<?> resourceClass, final TemplateProcessor templateProcessor) {
+ final String path = TemplateHelper.getTemplateName(viewable);
+ final Object templateReference = templateProcessor.resolve("/CustomViewableContext/" + path,
+ MediaType.TEXT_PLAIN_TYPE);
+
+ if (templateReference != null) {
+ return new ResolvedViewable(templateProcessor, templateReference, viewable, MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ return null;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/DefViewProcessor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/DefViewProcessor.java
new file mode 100644
index 0000000..06302db
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/DefViewProcessor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc.provider;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Michal Gajdos
+ */
+public class DefViewProcessor extends TestViewProcessor {
+
+ @Override
+ protected String getExtension() {
+ return ".def";
+ }
+
+ @Override
+ protected String getViewProcessorName() {
+ return "DefViewProcessor";
+ }
+
+ @Override
+ protected boolean acceptMediaType(final MediaType mediaType) {
+ return !new MediaType("application", "abc").equals(mediaType);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/TestViewProcessor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/TestViewProcessor.java
new file mode 100644
index 0000000..621256b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/provider/TestViewProcessor.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc.provider;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.Collection;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.server.mvc.spi.TemplateProcessor;
+import org.glassfish.jersey.server.validation.ValidationError;
+
+/**
+ * @author Paul Sandoz
+ * @author Michal Gajdos
+ */
+public class TestViewProcessor implements TemplateProcessor<String> {
+
+ @Override
+ public String resolve(String path, final MediaType mediaType) {
+ final String extension = getExtension();
+
+ if (!path.endsWith(extension)) {
+ path = path + extension;
+ }
+
+ final URL u = this.getClass().getResource(path);
+ if (u == null || !acceptMediaType(mediaType)) {
+ return null;
+ }
+ return path;
+ }
+
+ protected boolean acceptMediaType(final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public void writeTo(String templateReference, Viewable viewable, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream out) throws IOException {
+
+ final PrintStream ps = new PrintStream(out);
+ ps.print("name=");
+ ps.print(getViewProcessorName());
+ ps.println();
+ ps.print("path=");
+ ps.print(templateReference);
+ ps.println();
+ ps.print("model=");
+ ps.print(getModel(viewable.getModel()));
+ ps.println();
+ }
+
+ private String getModel(final Object model) {
+ if (model instanceof Collection) {
+ StringBuilder builder = new StringBuilder();
+ for (final Object object : (Collection) model) {
+ builder.append(getModel(object)).append(',');
+ }
+ return builder.delete(builder.length() - 1, builder.length()).toString();
+ } else if (model instanceof ValidationError) {
+ final ValidationError error = (ValidationError) model;
+ return error.getMessageTemplate() + "_" + error.getPath() + "_" + error.getInvalidValue();
+ }
+ return model.toString();
+ }
+
+ protected String getExtension() {
+ return ".testp";
+ }
+
+ protected String getViewProcessorName() {
+ return "TestViewProcessor";
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest.java
new file mode 100644
index 0000000..719e1a5
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.mvc.spi;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Reader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.server.mvc.spi.AbstractTemplateProcessor;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.spi.TestContainerException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ AbstractTemplateProcessorTest.FactoryInstanceTest.class,
+ AbstractTemplateProcessorTest.FactoryInstanceNegativeTest.class,
+ AbstractTemplateProcessorTest.FactoryClassTest.class,
+ AbstractTemplateProcessorTest.FactoryClassNegativeTest.class,
+ AbstractTemplateProcessorTest.FactoryClassNameTest.class,
+ AbstractTemplateProcessorTest.FactoryClassNameNegativeTest.class,
+ AbstractTemplateProcessorTest.CachePositiveTest.class,
+ AbstractTemplateProcessorTest.CachePositiveStringTest.class,
+ AbstractTemplateProcessorTest.CacheNegativeTest.class,
+ AbstractTemplateProcessorTest.CacheInvalidTest.class
+})
+public class AbstractTemplateProcessorTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ @Template
+ public String get() {
+ return "ko";
+ }
+ }
+
+ public static class TestFactory {
+
+ private final String value;
+
+ public TestFactory() {
+ this("Injected Test Factory");
+ }
+
+ public TestFactory(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class FactoryTemplateProcessor extends AbstractTemplateProcessor<String> {
+
+ private final TestFactory factory;
+
+ @Inject
+ public FactoryTemplateProcessor(Configuration config, InjectionManager injectionManager) {
+ super(config, injectionManager.getInstance(ServletContext.class), "factory", "fct");
+
+ this.factory = getTemplateObjectFactory(injectionManager::createAndInitialize, TestFactory.class, Values.lazy(
+ (Value<TestFactory>) () -> new TestFactory("Default Test Factory")));
+ }
+
+ @Override
+ protected String resolve(final String templatePath, final Reader reader) throws Exception {
+ return factory.value;
+ }
+
+ @Override
+ public void writeTo(final String templateReference, final Viewable viewable, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream out)
+ throws IOException {
+ out.write(templateReference.getBytes());
+ }
+ }
+
+ public abstract static class FactoryTest extends JerseyTest {
+
+ private final String expectedMessage;
+
+ FactoryTest(final Object factory, final String expectedMessage) throws TestContainerException {
+ super(new ResourceConfig(Resource.class)
+ .register(MvcFeature.class)
+ .register(FactoryTemplateProcessor.class)
+ .property(MvcFeature.TEMPLATE_OBJECT_FACTORY + ".factory", factory));
+
+ this.expectedMessage = expectedMessage;
+ }
+
+ @Test
+ public void testFactory() throws Exception {
+ final Response response = target().request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(expectedMessage));
+ }
+ }
+
+ public static class FactoryInstanceTest extends FactoryTest {
+
+ public FactoryInstanceTest() throws TestContainerException {
+ super(new TestFactory(), "Injected Test Factory");
+ }
+ }
+
+ public static class FactoryInstanceNegativeTest extends FactoryTest {
+
+ public FactoryInstanceNegativeTest() throws TestContainerException {
+ super("Default Test Factory", "Default Test Factory");
+ }
+ }
+
+ public static class FactoryClassTest extends FactoryTest {
+
+ public FactoryClassTest() throws TestContainerException {
+ super(TestFactory.class, "Injected Test Factory");
+ }
+ }
+
+ public static class FactoryClassNegativeTest extends FactoryTest {
+
+ public FactoryClassNegativeTest() throws TestContainerException {
+ super(String.class, "Default Test Factory");
+ }
+ }
+
+ public static class FactoryClassNameTest extends FactoryTest {
+
+ public FactoryClassNameTest() throws TestContainerException {
+ super(TestFactory.class.getName(), "Injected Test Factory");
+ }
+ }
+
+ public static class FactoryClassNameNegativeTest extends FactoryTest {
+
+ public FactoryClassNameNegativeTest() throws TestContainerException {
+ super(String.class.getName(), "Default Test Factory");
+ }
+ }
+
+ public static class CacheTemplateProcessor extends AbstractTemplateProcessor<String> {
+
+ private int i = 0;
+
+ @Inject
+ public CacheTemplateProcessor(Configuration config, InjectionManager injectionManager) {
+ super(config, injectionManager.getInstance(ServletContext.class), "factory", "fct");
+ }
+
+ @Override
+ protected String resolve(final String templatePath, final Reader reader) throws Exception {
+ return "" + i++;
+ }
+
+ @Override
+ public void writeTo(final String templateReference, final Viewable viewable, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream out) throws IOException {
+ out.write(templateReference.getBytes());
+ }
+ }
+
+ public abstract static class CacheTest extends JerseyTest {
+
+ private final boolean cache;
+
+ CacheTest(final Object cache) throws TestContainerException {
+ super(new ResourceConfig(Resource.class)
+ .register(MvcFeature.class)
+ .register(CacheTemplateProcessor.class)
+ .property(MvcFeature.CACHE_TEMPLATES + ".factory", cache));
+
+ this.cache = Boolean.valueOf(cache.toString());
+ }
+
+ @Test
+ public void testCache() throws Exception {
+ Response response = target().request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("0"));
+
+ response = target().request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(cache ? "0" : "1"));
+ }
+ }
+
+ public static class CachePositiveTest extends CacheTest {
+
+ public CachePositiveTest() throws TestContainerException {
+ super(true);
+ }
+ }
+
+ public static class CachePositiveStringTest extends CacheTest {
+
+ public CachePositiveStringTest() throws TestContainerException {
+ super("true");
+ }
+ }
+
+ public static class CacheNegativeTest extends CacheTest {
+
+ public CacheNegativeTest() throws TestContainerException {
+ super(false);
+ }
+ }
+
+ public static class CacheInvalidTest extends CacheTest {
+
+ public CacheInvalidTest() throws TestContainerException {
+ super("invalid");
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/package-info.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/package-info.java
new file mode 100644
index 0000000..c0fb065
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Jersey End to End server test classes.
+ */
+package org.glassfish.jersey.tests.e2e.server;
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/InheritanceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/InheritanceTest.java
new file mode 100644
index 0000000..5472975
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/InheritanceTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.routing;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class InheritanceTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class).register(WriterA.class).register(WriterB.class).register(WriterString.class);
+ }
+
+ public static class A {
+
+ String value;
+
+ public A() {
+ this.value = "a";
+ }
+
+ public A(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class B extends A {
+
+ public B() {
+ super("b");
+ }
+
+ public B(final String value) {
+ super("b" + value);
+ }
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public A getA() {
+ return new B("a");
+ }
+ }
+
+ public static class WriterA implements MessageBodyWriter<A> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return A.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(final A a, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final A a, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(("a" + a.value).getBytes());
+ }
+ }
+
+ @Produces({"text/plain"})
+ public static class WriterString implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(s.getBytes());
+ }
+ }
+
+ @Produces("b/b")
+ public static class WriterB implements MessageBodyWriter<B> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return B.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(final B b, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final B b,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(("b" + b.value).getBytes());
+ }
+ }
+
+ @Test
+ public void testWriterEntityInheritance() throws Exception {
+ assertThat(target().request("a/b").get(String.class), equalTo("aba"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/ResponseMediaTypeFromProvidersTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/ResponseMediaTypeFromProvidersTest.java
new file mode 100644
index 0000000..09ed78d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/ResponseMediaTypeFromProvidersTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.routing;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ResponseMediaTypeFromProvidersTest extends JerseyTest {
+
+ @Path("response")
+ public static class ResponseResource {
+
+ private List<String> getList() {
+ // must be an ArrayList. Arrays.asList creates Arrays$ArrayList.
+ return Arrays.asList("array", "list").stream().collect(Collectors.toCollection(ArrayList::new));
+ }
+
+ @GET
+ @Path("list")
+ public Response responseList() {
+ return Response.ok(getList()).build();
+ }
+ }
+
+ @Provider
+ public static class CollectionMessageBodyWriter implements MessageBodyWriter<Collection<?>> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(ArrayList.class) && genericType.equals(ArrayList.class);
+ }
+
+ @Override
+ public long getSize(final Collection<?> objects, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Collection<?> objects,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write("OK".getBytes());
+ }
+ }
+
+ @Provider
+ public static class IncorrectCollectionMessageBodyWriter implements MessageBodyWriter<Collection<?>> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return !new CollectionMessageBodyWriter().isWriteable(type, genericType, annotations, mediaType);
+ }
+
+ @Override
+ public long getSize(final Collection<?> objects, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Collection<?> objects,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write("ERROR".getBytes());
+ }
+ }
+
+ @Test
+ public void testResponseList() throws Exception {
+ final Response response = target("response").path("list").request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("OK"));
+ }
+
+ public static class StringBean {
+
+ private String value;
+
+ public StringBean() {
+ }
+
+ public StringBean(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ @Provider
+ public static class StringBeanMessageBodyWriter implements MessageBodyWriter<StringBean> {
+
+ public static MediaType STRING_BEAN_MT = new MediaType("string", "bean");
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(StringBean.class) && STRING_BEAN_MT.equals(mediaType);
+ }
+
+ @Override
+ public long getSize(final StringBean objects, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final StringBean objects,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(objects.getValue().getBytes());
+ }
+ }
+
+ @Path("AcceptableNonWriteableMethodResource")
+ public static class AcceptableNonWriteableMethodResource {
+
+ @GET
+ public StringBean getStringBean() {
+ return new StringBean("getStringBean");
+ }
+
+ @GET
+ @Produces("text/html")
+ public StringBean getTextHtml() {
+ return new StringBean("getTextHtml");
+ }
+
+ @GET
+ @Produces("text/xhtml")
+ public StringBean getTextXHtml() {
+ return new StringBean("getTextXHtml");
+ }
+
+ @POST
+ @Consumes("string/bean")
+ @Produces("string/bean")
+ public StringBean postStringBean(final StringBean stringBean) {
+ return stringBean;
+ }
+
+ @POST
+ @Produces("string/bean")
+ public StringBean postStringBean(final String string) {
+ return new StringBean("postStringBean_" + string);
+ }
+
+ @POST
+ @Consumes("string/bean")
+ @Path("response")
+ public Response postResponse(final StringBean stringBean) {
+ return Response.ok(stringBean).type("string/bean").build();
+ }
+
+ @POST
+ @Path("response")
+ public Response postResponse(final String string) {
+ return Response.ok(new StringBean("postStringBean_" + string)).type("string/bean").build();
+ }
+ }
+
+ @Test
+ public void testGetMethodRouting() throws Exception {
+ final Response response = target("AcceptableNonWriteableMethodResource").request("text/html", "text/xhtml",
+ "string/bean;q=0.2").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType(), equalTo(StringBeanMessageBodyWriter.STRING_BEAN_MT));
+ assertThat(response.readEntity(String.class), equalTo("getStringBean"));
+ }
+
+ @Test
+ public void testPostMethodRouting() throws Exception {
+ final Response response = target("AcceptableNonWriteableMethodResource").request("text/html", "text/xhtml",
+ "string/bean;q=0.2").post(Entity.entity("value", "string/bean"));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType(), equalTo(StringBeanMessageBodyWriter.STRING_BEAN_MT));
+ assertThat(response.readEntity(String.class), equalTo("postStringBean_value"));
+ }
+
+ @Test
+ public void testPostMethodRoutingWildcard() throws Exception {
+ final Response response = target("AcceptableNonWriteableMethodResource").request("*/*")
+ .post(Entity.entity("value", "string/bean"));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType(), equalTo(StringBeanMessageBodyWriter.STRING_BEAN_MT));
+ assertThat(response.readEntity(String.class), equalTo("postStringBean_value"));
+ }
+
+ @Test
+ public void testPostMethodRoutingResponse() throws Exception {
+ final Response response = target("AcceptableNonWriteableMethodResource").path("response").request()
+ .post(Entity.entity("value", "string/bean"));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.getMediaType(), equalTo(StringBeanMessageBodyWriter.STRING_BEAN_MT));
+ assertThat(response.readEntity(String.class), equalTo("postStringBean_value"));
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResponseResource.class, AcceptableNonWriteableMethodResource.class)
+ .register(CollectionMessageBodyWriter.class)
+ .register(IncorrectCollectionMessageBodyWriter.class)
+ .register(StringBeanMessageBodyWriter.class);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/CustomFeature.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/CustomFeature.java
new file mode 100644
index 0000000..3a37268
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/CustomFeature.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext1WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext2WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext3WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext4WriterInterceptor;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class CustomFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(Ext3WriterInterceptor.class, 1000);
+ context.register(Ext2WriterInterceptor.class, 100);
+ context.register(Ext1WriterInterceptor.INSTANCE, 500);
+ context.register(Ext4WriterInterceptor.INSTANCE, 1);
+ return true;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/RankedProviderScanningTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/RankedProviderScanningTest.java
new file mode 100644
index 0000000..9b5defa
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/RankedProviderScanningTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class RankedProviderScanningTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig().packages(false, RankedProviderScanningTest.class.getPackage().getName());
+ }
+
+ @Test
+ public void testRankedProviderScanning() throws Exception {
+ WebTarget t = target();
+ t.register(LoggingFeature.class);
+
+ Response r = t.path("/").request().get();
+
+ assertEquals(200, r.getStatus());
+ assertEquals("get-ext4-ext2-ext1-ext3", r.readEntity(String.class));
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/Resource.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/Resource.java
new file mode 100644
index 0000000..916ec20
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/Resource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Configuration;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext1WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext2WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext3WriterInterceptor;
+import org.glassfish.jersey.tests.e2e.server.scanning.ext.Ext4WriterInterceptor;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+* @author Michal Gajdos
+*/
+@Path("/")
+public class Resource {
+
+ private final Configuration config;
+
+ @Inject
+ public Resource(final Configuration config) {
+ this.config = config;
+ }
+
+ @GET
+ public String get() {
+ assertTrue(config.getClasses().size() >= 4); // e.g. WADL resource can be there too.
+ assertTrue(config.isRegistered(CustomFeature.class));
+ assertTrue(config.isRegistered(Ext2WriterInterceptor.class));
+ assertTrue(config.isRegistered(Ext3WriterInterceptor.class));
+ assertTrue(config.isRegistered(Resource.class));
+ assertTrue(config.getClasses().contains(CustomFeature.class));
+ assertTrue(config.getClasses().contains(Ext2WriterInterceptor.class));
+ assertTrue(config.getClasses().contains(Ext3WriterInterceptor.class));
+ assertTrue(config.getClasses().contains(Resource.class));
+
+ assertTrue(config.getInstances().size() >= 2);
+ assertTrue(config.getInstances().contains(Ext1WriterInterceptor.INSTANCE));
+ assertTrue(config.getInstances().contains(Ext4WriterInterceptor.INSTANCE));
+ assertTrue(config.isRegistered(Ext1WriterInterceptor.class));
+ assertTrue(config.isRegistered(Ext4WriterInterceptor.class));
+
+ assertTrue(config.isEnabled(CustomFeature.class));
+
+ return "get";
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext1WriterInterceptor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext1WriterInterceptor.java
new file mode 100644
index 0000000..c7ab2ea
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext1WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext1WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext1WriterInterceptor INSTANCE = new Ext1WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext1");
+ context.proceed();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext2WriterInterceptor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext2WriterInterceptor.java
new file mode 100644
index 0000000..2da3a23
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext2WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext2WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext2");
+ context.proceed();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext3WriterInterceptor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext3WriterInterceptor.java
new file mode 100644
index 0000000..b01e46e
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext3WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext3WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext3");
+ context.proceed();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext4WriterInterceptor.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext4WriterInterceptor.java
new file mode 100644
index 0000000..b1aca63
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/scanning/ext/Ext4WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.scanning.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext4WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext4WriterInterceptor INSTANCE = new Ext4WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext4");
+ context.proceed();
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicBadSubResource.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicBadSubResource.java
new file mode 100644
index 0000000..aaa9b86
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicBadSubResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+
+import javax.validation.constraints.Null;
+
+/**
+ * @author Michal Gajdos
+ */
+public class BasicBadSubResource {
+
+ @Context
+ @Null
+ private ResourceContext resourceContext;
+
+ @GET
+ public String get() {
+ throw new RuntimeException("Should not get here.");
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicResource.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicResource.java
new file mode 100644
index 0000000..90c5938
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicResource.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Null;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("beanvalidation")
+public class BasicResource {
+
+ @NotNull
+ @Context
+ private ResourceContext resourceContext;
+
+ private String getInputParamsResponse(final String path,
+ final String matrix,
+ final String query,
+ final String header,
+ final String cookie,
+ final String form) {
+
+ return path + '_' + matrix + '_' + query + '_' + header + '_' + cookie + '_' + form;
+ }
+
+ @POST
+ @Path("basicParam/{path: .*}")
+ @Consumes("application/x-www-form-urlencoded")
+ @SuppressWarnings("UnusedParameters")
+ public String validateParametersBasicConstraint(
+ @NotNull @PathParam("path") final String path,
+ @NotNull @MatrixParam("matrix") final String matrix,
+ @NotNull @QueryParam("query") final String query,
+ @NotNull @HeaderParam("header") final String header,
+ @NotNull @CookieParam("cookie") final String cookie,
+ @NotNull @FormParam("form") final String form,
+ @NotNull @Context final Request request) {
+
+ return getInputParamsResponse(path, matrix, query, header, cookie, form);
+ }
+
+ @POST
+ @Path("basicDefaultParam/{path: .*}")
+ @Consumes("application/x-www-form-urlencoded")
+ @SuppressWarnings("UnusedParameters")
+ public String validateParametersDefaultBasicConstraint(
+ @NotNull @DefaultValue("pathParam") @PathParam("path") final String path,
+ @NotNull @DefaultValue("matrixParam") @MatrixParam("matrix") final String matrix,
+ @NotNull @DefaultValue("queryParam") @QueryParam("query") final String query,
+ @NotNull @DefaultValue("headerParam") @HeaderParam("header") final String header,
+ @NotNull @DefaultValue("cookieParam") @CookieParam("cookie") final String cookie,
+ @NotNull @DefaultValue("formParam") @FormParam("form") final String form,
+ @NotNull @Context final Request request) {
+
+ return getInputParamsResponse(path, matrix, query, header, cookie, form);
+ }
+
+ @POST
+ @Path("customParam/{path: .*}")
+ @Consumes("application/x-www-form-urlencoded")
+ public String validateParametersCustomConstraint(
+ @ParamConstraint @PathParam("path") final String path,
+ @ParamConstraint @MatrixParam("matrix") final String matrix,
+ @ParamConstraint @QueryParam("query") final String query,
+ @ParamConstraint @HeaderParam("header") final String header,
+ @ParamConstraint @CookieParam("cookie") final String cookie,
+ @ParamConstraint @FormParam("form") final String form) {
+
+ return getInputParamsResponse(path, matrix, query, header, cookie, form);
+ }
+
+ @POST
+ @Path("mixedParam/{path: .*}")
+ @Consumes("application/x-www-form-urlencoded")
+ public String validateParametersMixedConstraint(
+ @Size(max = 11) @ParamConstraint @PathParam("path") final String path,
+ @Size(max = 11) @ParamConstraint @MatrixParam("matrix") final String matrix,
+ @Size(max = 11) @ParamConstraint @QueryParam("query") final String query,
+ @Size(max = 11) @ParamConstraint @HeaderParam("header") final String header,
+ @Size(max = 11) @ParamConstraint @CookieParam("cookie") final String cookie,
+ @Size(max = 11) @ParamConstraint @FormParam("form") final String form) {
+
+ return getInputParamsResponse(path, matrix, query, header, cookie, form);
+ }
+
+ @POST
+ @Path("multipleParam/{path: .*}")
+ @Consumes("application/x-www-form-urlencoded")
+ public String validateParametersMultipleConstraint(
+ @MultipleParamConstraint @PathParam("path") final String path,
+ @MultipleParamConstraint @MatrixParam("matrix") final String matrix,
+ @MultipleParamConstraint @QueryParam("query") final String query,
+ @MultipleParamConstraint @HeaderParam("header") final String header,
+ @MultipleParamConstraint @CookieParam("cookie") final String cookie,
+ @MultipleParamConstraint @FormParam("form") final String form) {
+
+ return getInputParamsResponse(path, matrix, query, header, cookie, form);
+ }
+
+ @POST
+ @Path("emptyBeanParam")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ public ContactBean validateEmptyBeanParamConstraint(@NotNull final ContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("validBeanParam")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ public ContactBean validateValidBeanParamConstraint(@NotNull @Valid final ContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("customBeanParam")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ public ContactBean validateCustomBeanParamConstraint(@OneContact final ContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("emptyBeanResponse")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ @NotNull
+ public ContactBean validateEmptyBeanResponseConstraint(final ContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("validBeanResponse")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ @NotNull
+ @Valid
+ public ContactBean validateValidBeanResponseConstraint(final ContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("validBeanWrappedInResponse")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ @NotNull
+ @Valid
+ public Response validateValidBeanWrappedInResponseConstraint(final ContactBean bean) {
+ return Response.ok(bean).type("application/contactBean").build();
+ }
+
+ @POST
+ @Path("customBeanResponse")
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ @OneContact
+ public ContactBean validateCustomBeanResponseConstraint(final ContactBean bean) {
+ return bean;
+ }
+
+ @GET
+ @Path("invalidContext")
+ @SuppressWarnings("UnusedParameters")
+ public Response invalidContext(@Null @Context final Request request) {
+ return Response.status(500).build();
+ }
+
+ @Path("sub/validResourceContextInstance")
+ public BasicSubResource getSubResourceValidResourceContextInstance() {
+ return resourceContext.initResource(new BasicSubResource(resourceContext));
+ }
+
+ @Path("sub/nullResourceContextInstance")
+ public BasicSubResource getSubResourceNullResourceContextInstance() {
+ return resourceContext.initResource(new BasicSubResource(null));
+ }
+
+ @Path("sub/nullResourceContextClass")
+ public BasicSubResource getSubResourceNullResourceContextClass() {
+ return resourceContext.getResource(BasicSubResource.class);
+ }
+
+ @Path("sub/wrong")
+ public BasicBadSubResource getWrongSubResource() {
+ return resourceContext.getResource(BasicBadSubResource.class);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicSubResource.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicSubResource.java
new file mode 100644
index 0000000..f5c0e14
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicSubResource.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+
+import org.hibernate.validator.constraints.Email;
+
+/**
+ * @author Michal Gajdos
+ */
+@NonEmptyNames
+@ValidateOnExecution(type = ExecutableType.ALL)
+public class BasicSubResource {
+
+ @NotNull
+ @FormParam("firstName")
+ private String firstName;
+
+ @NotNull
+ @FormParam("lastName")
+ private String lastName;
+
+ private String email;
+
+ /**
+ * Note: Constructor input parameter should not be validated.
+ */
+ @SuppressWarnings("UnusedParameters")
+ public BasicSubResource(@NotNull @Context final ResourceContext resourceContext) {
+ }
+
+ @FormParam("email")
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ @NotNull
+ @Email(regexp = "[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}")
+ public String getEmail() {
+ return email;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ @POST
+ @Consumes("application/x-www-form-urlencoded")
+ @Produces("application/contactBean")
+ @Valid
+ public ContactBean postContactValidationBean() {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setName(firstName + " " + lastName);
+ contactBean.setEmail(getEmail());
+ return contactBean;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicValidationTest.java
new file mode 100644
index 0000000..954d472
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/BasicValidationTest.java
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class BasicValidationTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ final ResourceConfig resourceConfig = new ResourceConfig(BasicResource.class);
+
+ resourceConfig.register(ContactBeanProvider.class);
+ resourceConfig.register(MoxyXmlFeature.class);
+
+ resourceConfig.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
+
+ return resourceConfig;
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+ config.register(ContactBeanProvider.class);
+ config.register(MoxyXmlFeature.class);
+ }
+
+ @Consumes("application/contactBean")
+ @Produces("application/contactBean")
+ @Provider
+ public static class ContactBeanProvider implements MessageBodyReader<ContactBean>, MessageBodyWriter<ContactBean> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type.equals(ContactBean.class);
+ }
+
+ @Override
+ public ContactBean readFrom(Class<ContactBean> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ try {
+ final ObjectInputStream objectInputStream = new ObjectInputStream(entityStream);
+ return (ContactBean) objectInputStream.readObject();
+ } catch (Exception e) {
+ // do nothing.
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type.equals(ContactBean.class);
+ }
+
+ @Override
+ public long getSize(ContactBean contactBean,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(ContactBean contactBean,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ try {
+ new ObjectOutputStream(entityStream).writeObject(contactBean);
+ } catch (Exception e) {
+ // do nothing.
+ }
+ }
+ }
+
+ private static final class ParamBean {
+
+ @HeaderParam("header")
+ private String headerParam;
+
+ @PathParam("path")
+ private String pathParam;
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @QueryParam("query")
+ private String queryParam;
+
+ @CookieParam("cookie")
+ private String cookie;
+
+ @FormParam("form")
+ private String formParam;
+
+ public ParamBean() {
+ }
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public void setCookie(String cookie) {
+ this.cookie = cookie;
+ }
+
+ public String getFormParam() {
+ return formParam;
+ }
+
+ public void setFormParam(String formParam) {
+ this.formParam = formParam;
+ }
+
+ public String getHeaderParam() {
+ return headerParam;
+ }
+
+ public void setHeaderParam(String headerParam) {
+ this.headerParam = headerParam;
+ }
+
+ public String getMatrixParam() {
+ return matrixParam;
+ }
+
+ public void setMatrixParam(String matrixParam) {
+ this.matrixParam = matrixParam;
+ }
+
+ public String getPathParam() {
+ return pathParam;
+ }
+
+ public void setPathParam(String pathParam) {
+ this.pathParam = pathParam;
+ }
+
+ public String getQueryParam() {
+ return queryParam;
+ }
+
+ public void setQueryParam(String queryParam) {
+ this.queryParam = queryParam;
+ }
+
+ @Override
+ public String toString() {
+ return "Bean{"
+ + "cookie='" + cookie + '\''
+ + ", formParam='" + formParam + '\''
+ + ", headerParam='" + headerParam + '\''
+ + ", matrixParam='" + matrixParam + '\''
+ + ", pathParam='" + pathParam + '\''
+ + ", queryParam='" + queryParam + '\''
+ + '}';
+ }
+ }
+
+ private ParamBean getDefaultParamBean() {
+ final ParamBean paramBean = new ParamBean();
+ paramBean.setCookie("cookieParam");
+ paramBean.setFormParam("formParam");
+ paramBean.setHeaderParam("headerParam");
+ paramBean.setMatrixParam("matrixParam");
+ paramBean.setPathParam("pathParam");
+ paramBean.setQueryParam("queryParam");
+ return paramBean;
+ }
+
+ private Response testInputParams(final String path, final ParamBean paramBean) throws Exception {
+ final Form form = new Form();
+ form.asMap().put("form", Arrays.asList(paramBean.getFormParam()));
+
+ WebTarget target = target("beanvalidation").path(path);
+
+ if (paramBean.getPathParam() != null) {
+ target = target.path(paramBean.getPathParam());
+ } else {
+ target = target.path("/");
+ }
+
+ Invocation.Builder request = target
+ .matrixParam("matrix", paramBean.getMatrixParam())
+ .queryParam("query", paramBean.getQueryParam())
+ .request();
+
+ if (paramBean.getHeaderParam() != null) {
+ request = request.header("header", paramBean.getHeaderParam());
+ }
+
+ if (paramBean.getCookie() != null) {
+ request = request.cookie("cookie", paramBean.getCookie());
+ }
+
+ return request.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ }
+
+ @Test
+ public void testInputParamsBasicConstraintsPositive() throws Exception {
+ final Response response = testInputParams("basicParam", getDefaultParamBean());
+
+ assertEquals(200, response.getStatus());
+ assertEquals("pathParam_matrixParam_queryParam_headerParam_cookieParam_formParam", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInputParamsBasicConstraintsNegative() throws Exception {
+ final Response response = testInputParams("basicParam", new ParamBean());
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg1")); // @MatrixParam
+ assertTrue(message.contains("arg2")); // @QueryParam
+ assertTrue(message.contains("arg3")); // @HeaderParam
+ assertTrue(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+
+ assertFalse(message.contains("arg0")); // @PathParam
+ assertFalse(message.contains("arg6")); // @Context
+ }
+
+ @Test
+ public void testInputParamsDefaultBasicConstraintsPositive() throws Exception {
+ final Response response = testInputParams("basicDefaultParam", new ParamBean());
+
+ assertEquals(200, response.getStatus());
+ assertEquals("_matrixParam_queryParam_headerParam_cookieParam_formParam", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInputParamsCustomConstraintsPositive() throws Exception {
+ final Response response = testInputParams("customParam", getDefaultParamBean());
+
+ assertEquals(200, response.getStatus());
+ assertEquals("pathParam_matrixParam_queryParam_headerParam_cookieParam_formParam", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInputParamsCustomConstraintsNegative() throws Exception {
+ final Response response = testInputParams("customParam", new ParamBean());
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0")); // @PathParam
+ assertTrue(message.contains("arg1")); // @MatrixParam
+ assertTrue(message.contains("arg2")); // @QueryParam
+ assertTrue(message.contains("arg3")); // @HeaderParam
+ assertTrue(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+ }
+
+ @Test
+ public void testInputParamsMixedConstraintsPositive() throws Exception {
+ final Response response = testInputParams("mixedParam", getDefaultParamBean());
+
+ assertEquals(200, response.getStatus());
+ assertEquals("pathParam_matrixParam_queryParam_headerParam_cookieParam_formParam", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInputParamsMixedConstraintsNegative() throws Exception {
+ final Response response = testInputParams("mixedParam", new ParamBean());
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0")); // @PathParam
+ assertTrue(message.contains("arg1")); // @MatrixParam
+ assertTrue(message.contains("arg2")); // @QueryParam
+ assertTrue(message.contains("arg3")); // @HeaderParam
+ assertTrue(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+ }
+
+ @Test
+ public void testInputParamsMixedConstraintsNegativeTooLong() throws Exception {
+ final ParamBean defaultParamBean = getDefaultParamBean();
+ final String formParam = defaultParamBean.getFormParam();
+ defaultParamBean.setFormParam(formParam + formParam);
+
+ final Response response = testInputParams("mixedParam", defaultParamBean);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertFalse(message.contains("arg0")); // @PathParam
+ assertFalse(message.contains("arg1")); // @MatrixParam
+ assertFalse(message.contains("arg2")); // @QueryParam
+ assertFalse(message.contains("arg3")); // @HeaderParam
+ assertFalse(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+ }
+
+ @Test
+ public void testInputParamsMultipleConstraintsPositive() throws Exception {
+ final Response response = testInputParams("multipleParam", getDefaultParamBean());
+
+ assertEquals(200, response.getStatus());
+ assertEquals("pathParam_matrixParam_queryParam_headerParam_cookieParam_formParam", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInputParamsMultipleConstraintsNegative() throws Exception {
+ final Response response = testInputParams("multipleParam", new ParamBean());
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0")); // @PathParam
+ assertTrue(message.contains("arg1")); // @MatrixParam
+ assertTrue(message.contains("arg2")); // @QueryParam
+ assertTrue(message.contains("arg3")); // @HeaderParam
+ assertTrue(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+ }
+
+ @Test
+ public void testInputParamsMultipleConstraintsNegativeTooLong() throws Exception {
+ final ParamBean defaultParamBean = getDefaultParamBean();
+ final String formParam = defaultParamBean.getFormParam();
+ defaultParamBean.setFormParam(formParam + formParam);
+
+ final Response response = testInputParams("mixedParam", defaultParamBean);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertFalse(message.contains("arg0")); // @PathParam
+ assertFalse(message.contains("arg1")); // @MatrixParam
+ assertFalse(message.contains("arg2")); // @QueryParam
+ assertFalse(message.contains("arg3")); // @HeaderParam
+ assertFalse(message.contains("arg4")); // @CookieParam
+ assertTrue(message.contains("arg5")); // @FormParam
+ }
+
+ private Response testBean(final String path, final ContactBean contactBean) {
+ return target("beanvalidation")
+ .path(path)
+ .request("application/contactBean").post(Entity.entity(contactBean, "application/contactBean"));
+ }
+
+ @Test
+ public void testEmptyBeanParamPositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ final Response response = testBean("emptyBeanParam", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testEmptyBeanParamNegative() throws Exception {
+ final Response response = testBean("emptyBeanParam", null);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0"));
+ }
+
+ @Test
+ public void testValidBeanParamPositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setName("Jersey");
+ contactBean.setEmail("jersey@example.com");
+ final Response response = testBean("validBeanParam", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testValidBeanParamNegative() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ // Add value to pass @OneContact constraint but fails on @Pattern constraint defined on getter.
+ contactBean.setPhone("12");
+ final Response response = testBean("validBeanParam", contactBean);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0"));
+ }
+
+ @Test
+ public void testCustomBeanParamPositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setEmail("jersey@example.com");
+
+ final Response response = testBean("customBeanParam", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testCustomBeanParamNegative() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setEmail("jersey@example.com");
+ contactBean.setPhone("134539");
+
+ final Response response = testBean("customBeanParam", contactBean);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0"));
+ }
+
+ @Test
+ public void testEmptyBeanResponsePositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ final Response response = testBean("emptyBeanResponse", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testEmptyBeanResponseNegative() throws Exception {
+ final Response response = testBean("emptyBeanResponse", null);
+
+ assertEquals(500, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("return value"));
+ }
+
+ @Test
+ public void testValidBeanResponsePositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setName("Jersey");
+ contactBean.setEmail("jersey@example.com");
+ final Response response = testBean("validBeanResponse", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testValidBeanResponseNegative() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ final Response response = testBean("validBeanResponse", contactBean);
+
+ assertEquals(500, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("return value"));
+ }
+
+ @Test
+ public void testValidBeanWrappedInResponsePositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setName("Jersey");
+ contactBean.setEmail("jersey@example.com");
+ final Response response = testBean("validBeanWrappedInResponse", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testValidBeanWrappedInResponseNegative() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ final Response response = testBean("validBeanWrappedInResponse", contactBean);
+
+ assertEquals(500, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("return value"));
+ }
+
+ @Test
+ public void testCustomBeanResponsePositive() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setEmail("jersey@example.com");
+ final Response response = testBean("customBeanResponse", contactBean);
+
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+
+ @Test
+ public void testCustomBeanResponseNegative() throws Exception {
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setEmail("jersey@example.com");
+ contactBean.setPhone("134539");
+
+ final Response response = testBean("customBeanResponse", contactBean);
+
+ assertEquals(500, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("return value"));
+ }
+
+ @Test
+ public void testInvalidContextValidation() throws Exception {
+ final Response response = target("beanvalidation").path("invalidContext").request().get();
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("arg0"));
+ }
+
+ private Response testSubResource(final String path, final Form form) throws Exception {
+ return target("beanvalidation")
+ .path("sub")
+ .path(path)
+ .request()
+ .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+ }
+
+ private void testSubResourcePositive(final String path) throws Exception {
+ testSubResource(path, false);
+ }
+
+ private void testSubResource(final String path, final boolean omitEmail) throws Exception {
+ final Form form = new Form();
+ form.asMap().put("firstName", Arrays.asList("Jersey"));
+ form.asMap().put("lastName", Arrays.asList("JAX-RS"));
+ if (!omitEmail) {
+ form.asMap().put("email", Arrays.asList("jersey@example.com"));
+ }
+
+ final ContactBean contactBean = new ContactBean();
+ contactBean.setName("Jersey JAX-RS");
+ contactBean.setEmail("jersey@example.com");
+
+ final Response response = testSubResource(path, form);
+
+ if (omitEmail) {
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("email"));
+ } else {
+ assertEquals(200, response.getStatus());
+ assertEquals(contactBean, response.readEntity(ContactBean.class));
+ }
+ }
+
+ private void testSubResourceNegative(final String path) throws Exception {
+ final Form form = new Form();
+ form.asMap().put("foo", Arrays.asList("bar"));
+
+ final Response response = testSubResource(path, form);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("firstName"));
+ assertTrue(message.contains("lastName"));
+ assertTrue(message.contains("email"));
+ }
+
+ @Test
+ public void testSubResourceValidResourceContextPositive() throws Exception {
+ testSubResourcePositive("validResourceContextInstance");
+ }
+
+ @Test
+ public void testSubResourceNullResourceContextPositive() throws Exception {
+ testSubResourcePositive("nullResourceContextInstance");
+ }
+
+ @Test
+ public void testSubResourceNullResourceContextClassPositive() throws Exception {
+ testSubResourcePositive("nullResourceContextClass");
+ }
+
+ @Test
+ public void testSubResourceValidResourceContextNegative() throws Exception {
+ testSubResourceNegative("validResourceContextInstance");
+ }
+
+ @Test
+ public void testSubResourceNullResourceContextNegative() throws Exception {
+ testSubResourceNegative("nullResourceContextInstance");
+ }
+
+ @Test
+ public void testSubResourceEmptyNames() throws Exception {
+ final Form form = new Form();
+ form.asMap().put("firstName", Arrays.asList(""));
+ form.asMap().put("lastName", Arrays.asList(""));
+
+ final Response response = testSubResource("nullResourceContextInstance", form);
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("at least one of the names is empty"));
+ }
+
+ @Test
+ public void testSubResourcePropertyNegative() throws Exception {
+ testSubResource("validResourceContextInstance", true);
+ }
+
+ @Test
+ public void testWrongSubResourceNegative() throws Exception {
+ final Response response = target("beanvalidation")
+ .path("sub/wrong")
+ .request()
+ .get();
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+ assertTrue(message.contains("resourceContext"));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ContactBean.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ContactBean.java
new file mode 100644
index 0000000..bad13ae
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ContactBean.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.io.Serializable;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotBlank;
+
+/**
+ * @author Michal Gajdos
+ */
+@OneContact
+public class ContactBean implements Serializable {
+
+ @Email(regexp = "[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}")
+ private String email;
+
+ private String phone;
+
+ @NotBlank
+ private String name;
+
+ @NotNull(groups = {Extended.class})
+ private String city;
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ @Pattern(regexp = "[0-9]{3,9}")
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(final String phone) {
+ this.phone = phone;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ContactBean)) {
+ return false;
+ }
+
+ final ContactBean that = (ContactBean) o;
+
+ if (email != null ? !email.equals(that.email) : that.email != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (phone != null ? !phone.equals(that.phone) : that.phone != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = email != null ? email.hashCode() : 0;
+ result = 31 * result + (phone != null ? phone.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ContactBean{"
+ + "email='" + email + '\''
+ + ", phone='" + phone + '\''
+ + ", name='" + name + '\''
+ + '}';
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomBean.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomBean.java
new file mode 100644
index 0000000..fba9532
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomBean.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.validation.constraints.NotNull;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+/**
+ * @author Michal Gajdos
+ */
+@XmlRootElement
+@CustomValidation
+public class CustomBean {
+
+ @NotNull
+ private String path;
+
+ private boolean validate = true;
+
+ public void setPath(final String path) {
+ this.path = path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ @XmlTransient
+ public boolean isValidate() {
+ return validate;
+ }
+
+ public void setValidate(final boolean validate) {
+ this.validate = validate;
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomConfigValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomConfigValidationTest.java
new file mode 100644
index 0000000..de5aefb
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomConfigValidationTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.Path;
+import javax.validation.TraversableResolver;
+import javax.validation.Valid;
+import javax.validation.Validation;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.validation.ValidationConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.eclipse.persistence.jaxb.BeanValidationMode;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class CustomConfigValidationTest extends JerseyTest {
+
+ @javax.ws.rs.Path("customconfigvalidation/{path: .*}")
+ public static class CustomConfigResource {
+
+ @POST
+ @Consumes("application/xml")
+ @Produces("application/xml")
+ @NotNull
+ @Valid
+ public CustomBean post(@PathParam("path") final String path, final CustomBean beanParameter,
+ @Size(min = 5) @HeaderParam("myHeader") final String header) {
+ if ("".equals(path)) {
+ beanParameter.setPath(null);
+ beanParameter.setValidate(false);
+ } else {
+ beanParameter.setPath(path);
+ beanParameter.setValidate(true);
+ }
+ return beanParameter;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ final ResourceConfig resourceConfig = new ResourceConfig(CustomConfigResource.class);
+
+ // Turn off BV in MOXy otherwise the entities on server would be validated at incorrect times.
+ resourceConfig.register(moxyXmlFeature());
+ resourceConfig.register(ValidationConfigurationContextResolver.class);
+
+ resourceConfig.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
+
+ return resourceConfig;
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+
+ // Turn off BV in MOXy otherwise the entities on client would be validated as well.
+ config.register(moxyXmlFeature());
+ }
+
+ private MoxyXmlFeature moxyXmlFeature() {
+ return new MoxyXmlFeature(new HashMap<String, Object>() {{
+ put(MarshallerProperties.BEAN_VALIDATION_MODE, BeanValidationMode.NONE);
+ }},
+ Thread.currentThread().getContextClassLoader(),
+ false
+ );
+ }
+
+ @Test
+ public void testPositive() throws Exception {
+ final Response response = target("customconfigvalidation")
+ .path("ok")
+ .request()
+ .header("myHeader", "12345")
+ .post(Entity.entity(new CustomBean(), MediaType.APPLICATION_XML_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("ok", response.readEntity(CustomBean.class).getPath());
+ }
+
+ @Test
+ public void testParameterNameWithInterpolator() throws Exception {
+ final Response response = target("customconfigvalidation")
+ .path("ok")
+ .request()
+ .header("myHeader", "1234")
+ .post(Entity.entity(new CustomBean(), MediaType.APPLICATION_XML_TYPE));
+
+ assertEquals(400, response.getStatus());
+
+ final String message = response.readEntity(String.class);
+
+ assertFalse(message.contains("arg2"));
+ assertTrue(message.contains("header"));
+ assertFalse(message.contains("size must be between"));
+ assertTrue(message.contains("message"));
+ }
+
+ @Test
+ public void testTraversableResolver() throws Exception {
+ final Response response = target("customconfigvalidation/")
+ .request()
+ .header("myHeader", "12345")
+ .post(Entity.entity(new CustomBean(), MediaType.APPLICATION_XML_TYPE));
+
+ assertEquals(200, response.getStatus());
+ // return value passed validation because of "corrupted" traversableresolver
+ assertEquals(null, response.readEntity(CustomBean.class).getPath());
+ }
+
+ public static class ValidationConfigurationContextResolver implements ContextResolver<ValidationConfig> {
+
+ private final ValidationConfig config;
+
+ public ValidationConfigurationContextResolver() {
+ config = new ValidationConfig();
+
+ // ConstraintValidatorFactory is set by default.
+ config.messageInterpolator(new CustomMessageInterpolator());
+ config.parameterNameProvider(new CustomParameterNameProvider());
+ config.traversableResolver(new CustomTraversableResolver());
+ }
+
+ @Override
+ public ValidationConfig getContext(final Class<?> type) {
+ return ValidationConfig.class.isAssignableFrom(type) ? config : null;
+ }
+ }
+
+ private static class CustomMessageInterpolator implements MessageInterpolator {
+
+ @Override
+ public String interpolate(final String messageTemplate, final Context context) {
+ return "message";
+ }
+
+ @Override
+ public String interpolate(final String messageTemplate, final Context context, final Locale locale) {
+ return "localized message";
+ }
+ }
+
+ private static class CustomParameterNameProvider implements ParameterNameProvider {
+
+ private final ParameterNameProvider nameProvider;
+
+ public CustomParameterNameProvider() {
+ nameProvider = Validation.byDefaultProvider().configure().getDefaultParameterNameProvider();
+ }
+
+ @Override
+ public List<String> getParameterNames(final Constructor<?> constructor) {
+ return nameProvider.getParameterNames(constructor);
+ }
+
+ @Override
+ public List<String> getParameterNames(final Method method) {
+ try {
+ final Method post = CustomConfigResource.class.getMethod("post", String.class, CustomBean.class, String.class);
+
+ if (method.equals(post)) {
+ return Arrays.asList("path", "beanParameter", "header");
+ }
+ } catch (final NoSuchMethodException e) {
+ // Do nothing.
+ }
+ return nameProvider.getParameterNames(method);
+ }
+ }
+
+ private static class CustomTraversableResolver implements TraversableResolver {
+
+ @Override
+ public boolean isReachable(final Object traversableObject,
+ final Path.Node traversableProperty,
+ final Class<?> rootBeanType,
+ final Path pathToTraversableObject,
+ final ElementType elementType) {
+ return false;
+ }
+
+ @Override
+ public boolean isCascadable(final Object traversableObject,
+ final Path.Node traversableProperty,
+ final Class<?> rootBeanType,
+ final Path pathToTraversableObject,
+ final ElementType elementType) {
+ return false;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomValidation.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomValidation.java
new file mode 100644
index 0000000..67a2d23
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/CustomValidation.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Michal Gajdos
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@NotNull
+@Constraint(validatedBy = CustomValidation.Validator.class)
+public @interface CustomValidation {
+
+ String message() default "client should never see this";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+
+ public static class Validator implements ConstraintValidator<CustomValidation, CustomBean> {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Override
+ public void initialize(final CustomValidation constraintAnnotation) {
+ }
+
+ @Override
+ public boolean isValid(final CustomBean bean, final ConstraintValidatorContext context) {
+ // !bean.isValidate() - to make sure this validation passes for CustomConfigValidationTest#testTraversableResolver
+ // (TraversableResolver is not invoked for ElementType.TYPE anymore).
+ return !bean.isValidate() || uriInfo.getPathParameters().getFirst("path").equals(bean.getPath());
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/EntityInheritanceValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/EntityInheritanceValidationTest.java
new file mode 100644
index 0000000..e505374
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/EntityInheritanceValidationTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.hibernate.validator.constraints.NotBlank;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Tests to ensure that validation constraints on a superclass are validated as well.
+ *
+ * @author Michal Gajdos
+ */
+public class EntityInheritanceValidationTest extends JerseyTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ @Produces("application/json")
+ public Entity post(@Valid final Entity entity) {
+ return entity;
+ }
+ }
+
+ public static class AbstractEntity {
+
+ private String text;
+
+ public AbstractEntity() {
+ }
+
+ public AbstractEntity(final String text) {
+ this.text = text;
+ }
+
+ @NotNull
+ @NotBlank
+ public String getText() {
+ return text;
+ }
+
+ public void setText(final String text) {
+ this.text = text;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final AbstractEntity that = (AbstractEntity) o;
+
+ if (!text.equals(that.text)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return text.hashCode();
+ }
+ }
+
+ public static class Entity extends AbstractEntity {
+
+ private Integer number;
+
+ public Entity() {
+ }
+
+ public Entity(final String text, final Integer number) {
+ super(text);
+ this.number = number;
+ }
+
+ @Min(12)
+ @Max(14)
+ @NotNull
+ public Integer getNumber() {
+ return number;
+ }
+
+ public void setNumber(final Integer number) {
+ this.number = number;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ final Entity entity = (Entity) o;
+
+ if (!number.equals(entity.number)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + number.hashCode();
+ return result;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class)
+ .register(JacksonFeature.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(JacksonFeature.class);
+ }
+
+ @Test
+ public void testEntityInheritance() throws Exception {
+ final Entity entity = new Entity("foo", 13);
+ final Response response = target().request().post(javax.ws.rs.client.Entity.json(entity));
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(Entity.class), is(entity));
+ }
+
+ @Test
+ public void testEntityInheritanceBlankText() throws Exception {
+ final Response response = target().request().post(javax.ws.rs.client.Entity.json(new Entity("", 13)));
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+ @Test
+ public void testEntityInheritanceInvalidNumber() throws Exception {
+ final Response response = target().request().post(javax.ws.rs.client.Entity.json(new Entity("foo", 23)));
+
+ assertThat(response.getStatus(), is(400));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/Extended.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/Extended.java
new file mode 100644
index 0000000..529fa09
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/Extended.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+/**
+ * @author Michal Gajdos
+ */
+public interface Extended {
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidation.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidation.java
new file mode 100644
index 0000000..4ebc5d7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidation.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
+
+/**
+ * @author Michal Gajdos
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = FieldPropertyValidation.Validator.class)
+public @interface FieldPropertyValidation {
+
+ String message() default "one or more fields are not valid";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+
+ String[] elements() default {};
+
+ public class Validator implements ConstraintValidator<FieldPropertyValidation, FieldPropertyValidationResource.SubResource> {
+
+ private List<String> properties;
+
+ @Override
+ public void initialize(final FieldPropertyValidation annotation) {
+ this.properties = Arrays.asList(annotation.elements());
+ }
+
+ @Override
+ public boolean isValid(final FieldPropertyValidationResource.SubResource bean,
+ final ConstraintValidatorContext constraintValidatorContext) {
+ boolean result = true;
+
+ for (final String property : properties) {
+ if ("fieldAndClass".equals(property)) {
+ result &= bean.fieldAndClass != null;
+ } else if ("propertyAndClass".equals(property)) {
+ result &= bean.getPropertyAndClass() != null;
+ } else if ("propertyGetterAndClass".equals(property)) {
+ result &= bean.getPropertyGetterAndClass() != null;
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationResource.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationResource.java
new file mode 100644
index 0000000..ea3c896
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationResource.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("fieldPropertyValidationResource")
+public class FieldPropertyValidationResource {
+
+ @Path("valid")
+ public SubResource valid() {
+ return new SubResource("valid", "valid", "valid", "valid", "valid", "valid");
+ }
+
+ @Path("invalidPropertyGetterAndClassNull")
+ public SubResource invalidPropertyGetterAndClassNull() {
+ return new SubResource("valid", "valid", "valid", "valid", "valid", null);
+ }
+
+ @Path("invalidPropertyGetterAndClassLong")
+ public SubResource invalidPropertyGetterAndClassLong() {
+ return new SubResource("valid", "valid", "valid", "valid", "valid", "valid-valid");
+ }
+
+ @Path("invalidPropertyAndClassNull")
+ public SubResource invalidPropertyAndClassNull() {
+ return new SubResource("valid", "valid", "valid", "valid", null, "valid");
+ }
+
+ @Path("invalidFieldAndClassNull")
+ public SubResource invalidFieldAndClassNull() {
+ return new SubResource("valid", "valid", "valid", null, "valid", "valid");
+ }
+
+ @Path("invalidPropertyGetterNull")
+ public SubResource invalidPropertyGetterNull() {
+ return new SubResource("valid", "valid", null, "valid", "valid", "valid");
+ }
+
+ @Path("invalidPropertyGetterLong")
+ public SubResource invalidPropertyGetterLong() {
+ return new SubResource("valid", "valid", "valid-valid", "valid", "valid", "valid");
+ }
+
+ @Path("invalidPropertyNull")
+ public SubResource invalidPropertyNull() {
+ return new SubResource("valid", null, "valid", "valid", "valid", "valid");
+ }
+
+ @Path("invalidFieldNull")
+ public SubResource invalidFieldNull() {
+ return new SubResource(null, "valid", "valid", null, "valid", "valid");
+ }
+
+ @FieldPropertyValidation(elements = {"fieldAndClass", "propertyAndClass", "propertyGetterAndClass"})
+ public static class SubResource {
+
+ @NotNull
+ @Size(min = 5)
+ final String field;
+
+ @NotNull
+ @Size(min = 5)
+ final String property;
+
+ @NotNull
+ @Size(min = 5)
+ final String propertyGetter;
+
+ final String fieldAndClass;
+
+ final String propertyAndClass;
+
+ final String propertyGetterAndClass;
+
+ public SubResource(final String field, final String property, final String propertyAndGetter,
+ final String fieldAndClass, final String propertyAndClass, final String propertyGetterAndClass) {
+ this.field = field;
+ this.property = property;
+ this.propertyGetter = propertyAndGetter;
+ this.fieldAndClass = fieldAndClass;
+ this.propertyAndClass = propertyAndClass;
+ this.propertyGetterAndClass = propertyGetterAndClass;
+ }
+
+ public String getProperty() {
+ return property;
+ }
+
+ @Size(max = 5)
+ public String getPropertyGetter() {
+ return propertyGetter;
+ }
+
+ public String getPropertyAndClass() {
+ return propertyAndClass;
+ }
+
+ @Size(max = 5)
+ public String getPropertyGetterAndClass() {
+ return propertyGetterAndClass;
+ }
+
+ @GET
+ public String method() {
+ return "ok";
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationTest.java
new file mode 100644
index 0000000..6750769
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/FieldPropertyValidationTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class FieldPropertyValidationTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FieldPropertyValidationResource.class);
+ }
+
+ @Test
+ public void testValid() throws Exception {
+ _test("valid", 200);
+ }
+
+ @Test
+ public void testInvalidPropertyGetterAndClassNull() throws Exception {
+ _test("invalidPropertyGetterAndClassNull", 400);
+ }
+
+ @Test
+ public void testInvalidPropertyGetterAndClassLong() throws Exception {
+ _test("invalidPropertyGetterAndClassLong", 400);
+ }
+
+ @Test
+ public void testInvalidPropertyAndClassNull() throws Exception {
+ _test("invalidPropertyAndClassNull", 400);
+ }
+
+ @Test
+ public void testInvalidFieldAndClassNull() throws Exception {
+ _test("invalidFieldAndClassNull", 400);
+ }
+
+ @Test
+ public void testInvalidPropertyGetterNull() throws Exception {
+ _test("invalidPropertyGetterNull", 400);
+ }
+
+ @Test
+ public void testInvalidPropertyGetterLong() throws Exception {
+ _test("invalidPropertyGetterLong", 400);
+ }
+
+ @Test
+ public void testInvalidPropertyNull() throws Exception {
+ _test("invalidPropertyNull", 400);
+ }
+
+ @Test
+ public void testInvalidFieldNull() throws Exception {
+ _test("invalidFieldNull", 400);
+ }
+
+ private void _test(final String path, final int status) {
+ final Response response = target("fieldPropertyValidationResource")
+ .path(path)
+ .request()
+ .get();
+
+ assertThat(response.getStatus(), equalTo(status));
+
+ if (status == 200) {
+ assertThat(response.readEntity(String.class), equalTo("ok"));
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/InheritanceValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/InheritanceValidationTest.java
new file mode 100644
index 0000000..a8fa2c8
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/InheritanceValidationTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class InheritanceValidationTest extends JerseyTest {
+
+ public static interface ResourceNumberInterface<T extends Number> {
+
+ @POST
+ @Min(0)
+ @NotNull
+ public T post(@NotNull @Max(100) final T value);
+ }
+
+ public static interface ResourceStringInterface {
+
+ @Min(-50)
+ public String post(@Max(50) final String value);
+ }
+
+ @Path("/")
+ public static class ResourceNumberString implements ResourceNumberInterface<Integer>, ResourceStringInterface {
+
+ @Override
+ public Integer post(final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("string")
+ @Override
+ public String post(final String value) {
+ return value;
+ }
+ }
+
+ @Path("/sub")
+ public static class SubClassResourceNumberString extends ResourceNumberString {
+
+ @Override
+ public Integer post(final Integer value) {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResourceNumberString.class, SubClassResourceNumberString.class);
+ }
+
+ @Test
+ public void testValidateNumberPositive() throws Exception {
+ _test(75, 200);
+ }
+
+ @Test
+ public void testValidateNumberInputNegative() throws Exception {
+ _test(150, 400);
+ }
+
+ @Test
+ public void testValidateStringPositive() throws Exception {
+ _test("string", "25", 200);
+ }
+
+ @Test
+ public void testValidateStringInputNegative() throws Exception {
+ _test("string", "150", 400);
+ }
+
+ @Test
+ public void testValidateNumberSubClassPositive() throws Exception {
+ _test("sub", 75, 200);
+ }
+
+ @Test
+ public void testValidateNumberInputSubClassNegative() throws Exception {
+ _test("sub", 150, 400);
+ }
+
+ @Test
+ public void testValidateStringSubClassPositive() throws Exception {
+ _test("sub/string", "25", 200);
+ }
+
+ @Test
+ public void testValidateStringInputSubClassNegative() throws Exception {
+ _test("sub/string", "150", 400);
+ }
+
+ @Test
+ public void testValidateNumberResponseNegative() throws Exception {
+ _test(-150, 500);
+ }
+
+ @Test
+ public void testValidateStringResponseNegative() throws Exception {
+ _test("string", "-150", 500);
+ }
+
+ @Test
+ public void testValidateNumberResponseSubClassNegative() throws Exception {
+ _test("sub", -150, 500);
+ }
+
+ @Test
+ public void testValidateStringResponseSubClassNegative() throws Exception {
+ _test("sub/string", "-150", 500);
+ }
+
+ private void _test(final Object value, final int responseStatus) {
+ _test("", value, responseStatus);
+ }
+
+ private void _test(final String path, final Object value, final int responseStatus) {
+ final Response response = target(path).request().post(Entity.text(value));
+
+ assertThat("Wrong response.", response.getStatus(), equalTo(responseStatus));
+
+ if (responseStatus == 200) {
+ assertThat("Invalid entity.", response.readEntity(value.getClass()), equalTo(value));
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/MultipleParamConstraint.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/MultipleParamConstraint.java
new file mode 100644
index 0000000..c17af49
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/MultipleParamConstraint.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Michal Gajdos
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = {})
+@ParamConstraint
+@Size(max = 11)
+public @interface MultipleParamConstraint {
+
+ String message() default "invalid parameter";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/NonEmptyNames.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/NonEmptyNames.java
new file mode 100644
index 0000000..ff29e02
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/NonEmptyNames.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
+
+/**
+ * @author Michal Gajdos
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = { NonEmptyNames.Validator.class })
+public @interface NonEmptyNames {
+
+ String message() default "{org.glassfish.jersey.tests.e2e.server.validation.NonEmptyNames.message}";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+
+ public class Validator implements ConstraintValidator<NonEmptyNames, BasicSubResource> {
+
+ @Override
+ public void initialize(final NonEmptyNames nonRecursive) {
+ }
+
+ @Override
+ public boolean isValid(final BasicSubResource resource, final ConstraintValidatorContext constraintValidatorContext) {
+ return isValid(resource.getFirstName()) && isValid(resource.getLastName());
+ }
+
+ private boolean isValid(final String name) {
+ // @NotNull checks null value
+ return name == null || !"".equals(name.trim());
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/OneContact.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/OneContact.java
new file mode 100644
index 0000000..c497cb5
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/OneContact.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Michal Gajdos
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@NotNull
+@Constraint(validatedBy = OneContact.Validator.class)
+public @interface OneContact {
+
+ String message() default "none or more than one contact";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+
+ public class Validator implements ConstraintValidator<OneContact, ContactBean> {
+
+ @Override
+ public void initialize(final OneContact nonRecursive) {
+ }
+
+ @Override
+ public boolean isValid(final ContactBean contactBean, final ConstraintValidatorContext constraintValidatorContext) {
+ if (contactBean.getEmail() == null && contactBean.getPhone() == null) {
+ return false;
+ }
+ return !(contactBean.getEmail() != null && contactBean.getPhone() != null);
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ParamConstraint.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ParamConstraint.java
new file mode 100644
index 0000000..6dd262b
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ParamConstraint.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+/**
+ * Valid: [a-zA-Z]+Param
+ *
+ * @author Michal Gajdos
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = {})
+@NotNull
+@Pattern(regexp = "^[a-zA-Z]+Param$")
+public @interface ParamConstraint {
+
+ String message() default "invalid parameter";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ProgrammaticValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ProgrammaticValidationTest.java
new file mode 100644
index 0000000..3b30812
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ProgrammaticValidationTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Bean Validation tests for programmatically created resources.
+ *
+ * @author Michal Gajdos
+ */
+public class ProgrammaticValidationTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ final Set<Resource> resources = new HashSet<>();
+
+ Resource.Builder resourceBuilder = Resource.builder("instance");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(new ValidationInflector());
+ resources.add(resourceBuilder.build());
+
+ resourceBuilder = Resource.builder("class");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(ValidationInflector.class);
+ resources.add(resourceBuilder.build());
+
+ try {
+ resourceBuilder = Resource.builder("methodInstanceClass");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(new ValidationInflector(), ValidationInflector.class.getMethod("get",
+ ContainerRequestContext.class));
+ resources.add(resourceBuilder.build());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException();
+ }
+
+ try {
+ resourceBuilder = Resource.builder("methodClassClass");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(ValidationInflector.class,
+ ValidationInflector.class.getMethod("get", ContainerRequestContext.class));
+ resources.add(resourceBuilder.build());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException();
+ }
+
+ try {
+ resourceBuilder = Resource.builder("methodInstanceInterface");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(new ValidationInflector(), Inflector.class.getMethod("apply", Object.class));
+ resources.add(resourceBuilder.build());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException();
+ }
+
+ try {
+ resourceBuilder = Resource.builder("methodClassInterface");
+ resourceBuilder
+ .addMethod("POST")
+ .handledBy(ValidationInflector.class, Inflector.class.getMethod("apply", Object.class));
+ resources.add(resourceBuilder.build());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException();
+ }
+
+ return new ResourceConfig().register(LoggingFeature.class).registerResources(resources);
+ }
+
+ @Test
+ public void testInflectorInstance() throws Exception {
+ final Response response = target("instance").request().post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorInstanceNegative() throws Exception {
+ final Response response = target("instance").request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testInflectorClass() throws Exception {
+ final Response response = target("class").request().post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorClassNegative() throws Exception {
+ final Response response = target("class").request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testInflectorMethodInstanceClass() throws Exception {
+ final Response response = target("methodInstanceClass").request().post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorMethodInstanceClassNegative() throws Exception {
+ final Response response = target("methodInstanceClass").request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testInflectorMethodClassClass() throws Exception {
+ final Response response = target("methodClassClass").request().post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorMethodClassClassNegative() throws Exception {
+ final Response response = target("methodClassClass").request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testInflectorMethodInstanceInterface() throws Exception {
+ final Response response = target("methodInstanceInterface").request()
+ .post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorMethodInstanceInterfaceNegative() throws Exception {
+ final Response response = target("methodInstanceInterface").request()
+ .post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testInflectorMethodClassInterface() throws Exception {
+ final Response response = target("methodClassInterface").request()
+ .post(Entity.entity("value", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("value", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testInflectorMethodClassInterfaceNegative() throws Exception {
+ final Response response = target("methodClassInterface").request().post(Entity.entity(null, MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(500, response.getStatus());
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/PropertyValidationTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/PropertyValidationTest.java
new file mode 100644
index 0000000..101ff5a
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/PropertyValidationTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.validation.ValidationFeature;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test various combinations of enabling/disabling: auto-discovery, bean validation, validation feature.
+ *
+ * @author Michal Gajdos
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class PropertyValidationTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ @NotNull
+ public String post(final String value) {
+ return value.isEmpty() ? null : value;
+ }
+ }
+
+ @Test
+ public void testDefaultValidationDefaultDiscoveryFeature() throws Exception {
+ _test(500, null, null, true);
+ }
+
+ @Test
+ public void testDefaultValidationDefaultDiscoveryNoFeature() throws Exception {
+ _test(500, null, null, false);
+ }
+
+ @Test
+ public void testDefaultValidationDiscoveryFeature() throws Exception {
+ _test(500, null, false, true);
+ }
+
+ @Test
+ public void testDefaultValidationDiscoveryNoFeature() throws Exception {
+ _test(500, null, false, false);
+ }
+
+ @Test
+ public void testDefaultValidationNoDiscoveryFeature() throws Exception {
+ _test(500, null, true, true);
+ }
+
+ @Test
+ public void testDefaultValidationNoDiscoveryNoFeature() throws Exception {
+ // Even though properties are disabled BV is registered.
+ _test(500, null, true, false);
+ }
+
+ @Test
+ public void testValidationDefaultDiscoveryFeature() throws Exception {
+ _test(500, false, null, true);
+ }
+
+ @Test
+ public void testValidationDefaultDiscoveryNoFeature() throws Exception {
+ _test(500, false, null, false);
+ }
+
+ @Test
+ public void testValidationDiscoveryFeature() throws Exception {
+ _test(500, false, false, true);
+ }
+
+ @Test
+ public void testValidationDiscoveryNoFeature() throws Exception {
+ _test(500, false, false, false);
+ }
+
+ @Test
+ public void testValidationNoDiscoveryFeature() throws Exception {
+ _test(500, false, true, true);
+ }
+
+ @Test
+ public void testValidationNoDiscoveryNoFeature() throws Exception {
+ // Even though properties are disabled BV is registered.
+ _test(500, false, true, false);
+ }
+
+ @Test
+ public void testNoValidationDefaultDiscoveryFeature() throws Exception {
+ _test(204, true, null, true);
+ }
+
+ @Test
+ public void testNoValidationDefaultDiscoveryNoFeature() throws Exception {
+ _test(204, true, null, false);
+ }
+
+ @Test
+ public void testNoValidationDiscoveryFeature() throws Exception {
+ _test(204, true, false, true);
+ }
+
+ @Test
+ public void testNoValidationDiscoveryNoFeature() throws Exception {
+ _test(204, true, false, false);
+ }
+
+ @Test
+ public void testNoValidationNoDiscoveryFeature() throws Exception {
+ _test(204, true, true, true);
+ }
+
+ @Test
+ public void testNoValidationNoDiscoveryNoFeature() throws Exception {
+ _test(204, true, true, false);
+ }
+
+ private void _test(final int responseStatus, final Boolean disableValidation,
+ final Boolean disableAutoDiscovery, final boolean registerFeature) throws Exception {
+ final URI uri = URI.create("/");
+
+ assertApply(responseStatus, initResourceConfig(disableValidation, disableAutoDiscovery, registerFeature), uri);
+
+ if (responseStatus == 500) {
+ // validation works - environment is validation friendly -> let's try to disable META-INF/services lookup
+ final ResourceConfig resourceConfig = initResourceConfig(disableValidation, disableAutoDiscovery, true);
+ resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
+
+ assertApply(500, resourceConfig, uri);
+ }
+ }
+
+ private ResourceConfig initResourceConfig(final Boolean disableValidation,
+ final Boolean disableAutoDiscovery, final boolean registerFeature) {
+ final ResourceConfig resourceConfig = new ResourceConfig(Resource.class).register(LoggingFeature.class);
+
+ if (registerFeature) {
+ resourceConfig.register(ValidationFeature.class);
+ }
+ if (disableAutoDiscovery != null) {
+ resourceConfig.property(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, disableAutoDiscovery);
+ }
+ if (disableValidation != null) {
+ resourceConfig.property(ServerProperties.BV_FEATURE_DISABLE, disableValidation);
+ }
+ return resourceConfig;
+ }
+
+ private void assertApply(int responseStatus, ResourceConfig resourceConfig, URI uri)
+ throws InterruptedException, ExecutionException {
+ final ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
+ final ContainerRequest requestContext = new ContainerRequest(uri, uri, "POST", null, new MapPropertiesDelegate());
+ final ContainerResponse containerResponse = applicationHandler.apply(requestContext).get();
+
+ assertEquals(responseStatus, containerResponse.getStatus());
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ValidationInflector.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ValidationInflector.java
new file mode 100644
index 0000000..7f7755f
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/ValidationInflector.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation;
+
+import java.io.IOException;
+
+import javax.ws.rs.container.ContainerRequestContext;
+
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.process.Inflector;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ValidationInflector implements Inflector<ContainerRequestContext, String> {
+
+ @NotNull
+ @Override
+ public String apply(final ContainerRequestContext requestContext) {
+ return get(requestContext);
+ }
+
+ @NotNull
+ public String get(@NotNull final ContainerRequestContext requestContext) {
+ try {
+ final String entity = ReaderWriter.readFromAsString(
+ requestContext.getEntityStream(),
+ requestContext.getMediaType());
+
+ return entity.isEmpty() ? null : entity;
+ } catch (IOException e) {
+ return "error";
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/AnotherContactBean.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/AnotherContactBean.java
new file mode 100644
index 0000000..451b791
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/AnotherContactBean.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import java.io.Serializable;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.tests.e2e.server.validation.Extended;
+
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotBlank;
+
+/**
+ * @author Michal Gajdos
+ */
+@XmlRootElement
+public class AnotherContactBean implements Serializable {
+
+ private String email;
+
+ private String phone;
+
+ @NotBlank
+ private String name;
+
+ @NotNull(groups = {Extended.class})
+ private String city;
+
+ public AnotherContactBean() {
+ }
+
+ public AnotherContactBean(final String email, final String phone, final String name, final String city) {
+ this.email = email;
+ this.phone = phone;
+ this.name = name;
+ this.city = city;
+ }
+
+ @Email(regexp = "[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}")
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ @Pattern(regexp = "[0-9]{3,9}")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(final String phone) {
+ this.phone = phone;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof AnotherContactBean)) {
+ return false;
+ }
+
+ final AnotherContactBean that = (AnotherContactBean) o;
+
+ if (email != null ? !email.equals(that.email) : that.email != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (phone != null ? !phone.equals(that.phone) : that.phone != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = email != null ? email.hashCode() : 0;
+ result = 31 * result + (phone != null ? phone.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "AnotherContactBean{"
+ + "email='" + email + '\''
+ + ", phone='" + phone + '\''
+ + ", name='" + name + '\''
+ + '}';
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionAbstractTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionAbstractTest.java
new file mode 100644
index 0000000..8ffb658
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionAbstractTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.RunSeparately;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public abstract class ValidateOnExecutionAbstractTest extends JerseyTest {
+
+ @Test
+ public void testOnMethodValidateInputPassValidateExecutableDefault() throws Exception {
+ _testOnMethod("validateExecutableDefault", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateInputFailValidateExecutableDefault() throws Exception {
+ _testOnMethod("validateExecutableDefault", 15, 400);
+ }
+
+ @Test
+ public void testOnMethodValidateInputPassValidateExecutableMatch() throws Exception {
+ _testOnMethod("validateExecutableMatch", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateInputFailValidateExecutableMatch() throws Exception {
+ _testOnMethod("validateExecutableMatch", 15, 400);
+ }
+
+ @Test
+ public void testOnMethodValidateInputPassValidateExecutableMiss() throws Exception {
+ _testOnMethod("validateExecutableMiss", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateInputPassBiggerValidateExecutableMiss() throws Exception {
+ _testOnMethod("validateExecutableMiss", 15, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateInputPassValidateExecutableNone() throws Exception {
+ _testOnMethod("validateExecutableNone", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateInputPassBiggerValidateExecutableNone() throws Exception {
+ _testOnMethod("validateExecutableNone", 15, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassValidateExecutableDefault() throws Exception {
+ _testOnMethod("validateExecutableDefault", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultFailValidateExecutableDefault() throws Exception {
+ _testOnMethod("validateExecutableDefault", -15, 500);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassValidateExecutableMatch() throws Exception {
+ _testOnMethod("validateExecutableMatch", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultFailValidateExecutableMatch() throws Exception {
+ _testOnMethod("validateExecutableMatch", -15, 500);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassValidateExecutableMiss() throws Exception {
+ _testOnMethod("validateExecutableMiss", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassBiggerValidateExecutableMiss() throws Exception {
+ _testOnMethod("validateExecutableMiss", -15, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassValidateExecutableNone() throws Exception {
+ _testOnMethod("validateExecutableNone", 0, 200);
+ }
+
+ @Test
+ public void testOnMethodValidateResultPassBiggerValidateExecutableNone() throws Exception {
+ _testOnMethod("validateExecutableNone", -15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableDefault() throws Exception {
+ _testOnType("default", 0, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableMatch() throws Exception {
+ _testOnType("match", 0, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputFailValidateExecutableMatch() throws Exception {
+ _testOnType("match", 15, 400);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableMiss() throws Exception {
+ _testOnType("miss", 0, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassBiggerValidateExecutableMiss() throws Exception {
+ _testOnType("miss", 15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableNone() throws Exception {
+ _testOnType("none", 0, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassBiggerValidateExecutableNone() throws Exception {
+ _testOnType("none", 15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassValidateExecutableDefault() throws Exception {
+ _testOnType("default", 0, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassValidateExecutableMatch() throws Exception {
+ _testOnType("match", 0, 200);
+ }
+
+ @Test
+ @RunSeparately
+ public void testOnTypeValidateResultFailValidateExecutableMatch() throws Exception {
+ _testOnType("match", -15, 500);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassValidateExecutableMiss() throws Exception {
+ _testOnType("miss", 0, 200);
+ }
+
+ @Test
+ @RunSeparately
+ public void testOnTypeValidateResultPassBiggerValidateExecutableMiss() throws Exception {
+ _testOnType("miss", -15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassValidateExecutableNone() throws Exception {
+ _testOnType("none", 0, 200);
+ }
+
+ @Test
+ @RunSeparately
+ public void testOnTypeValidateResultPassBiggerValidateExecutableNone() throws Exception {
+ _testOnType("none", -15, 200);
+ }
+
+ @Test
+ public void testMixedValidatePassDefault() throws Exception {
+ _test("mixed-default", 0, 200);
+ }
+
+ @Test
+ public void testMixedValidateInputFailDefault() throws Exception {
+ _test("mixed-default", 15, 400);
+ }
+
+ @Test
+ public void testMixedValidateResultFailDefault() throws Exception {
+ _test("mixed-default", -15, 500);
+ }
+
+ @Test
+ public void testMixedValidatePassNone() throws Exception {
+ _test("mixed-none", 0, 200);
+ }
+
+ @Test
+ public void testMixedValidateInputPassNone() throws Exception {
+ _test("mixed-none", 15, 200);
+ }
+
+ @Test
+ public void testMixedValidateResultPassNone() throws Exception {
+ _test("mixed-none", -15, 200);
+ }
+
+ void _testOnMethod(final String path, final Integer value, final int returnStatus) throws Exception {
+ _test("on-method/" + path, value, returnStatus);
+ }
+
+ void _testOnType(final String path, final Integer value, final int returnStatus) throws Exception {
+ _test("on-type-" + path, value, returnStatus);
+ }
+
+ void _test(final String path, final Integer value, final int returnStatus) throws Exception {
+ final Response response = target(path)
+ .request()
+ .post(Entity.text(value));
+
+ assertEquals(returnStatus, response.getStatus());
+
+ if (returnStatus == 200) {
+ assertEquals(value, response.readEntity(Integer.class));
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java
new file mode 100644
index 0000000..da00461
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.util.runner.RunSeparately;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+// @RunWith(ConcurrentRunner.class)
+public class ValidateOnExecutionBasicTest extends ValidateOnExecutionAbstractTest {
+
+ /**
+ * On METHOD.
+ */
+
+ @Path("on-method")
+ public static class ValidateExecutableOnMethodsResource {
+
+ @POST
+ @Path("validateExecutableDefault")
+ @ValidateOnExecution
+ @Min(0)
+ public Integer validateExecutableDefault(@Max(10) final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("validateExecutableMatch")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ @Min(0)
+ public Integer validateExecutableMatch(@Max(10) final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("validateExecutableMiss")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ @Min(0)
+ public Integer validateExecutableMiss(@Max(10) final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("validateExecutableNone")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ @Min(0)
+ public Integer validateExecutableNone(@Max(10) final Integer value) {
+ return value;
+ }
+ }
+
+ /**
+ * On TYPE.
+ */
+
+ public abstract static class ValidateExecutableOnType {
+
+ @POST
+ @Min(0)
+ public Integer validateExecutable(@Max(10) final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-default")
+ @ValidateOnExecution
+ public static class ValidateExecutableOnTypeDefault extends ValidateExecutableOnType {
+ }
+
+ @Path("on-type-match")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static class ValidateExecutableOnTypeMatch extends ValidateExecutableOnType {
+ }
+
+ @Path("on-type-miss")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public static class ValidateExecutableOnTypeMiss extends ValidateExecutableOnType {
+ }
+
+ @Path("on-type-none")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static class ValidateExecutableOnTypeNone extends ValidateExecutableOnType {
+ }
+
+ /**
+ * MIXED.
+ */
+
+ @Path("mixed-default")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static class ValidateExecutableMixedDefault {
+
+ @POST
+ @Min(0)
+ @ValidateOnExecution
+ public Integer validateExecutable(@Max(10) final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("mixed-none")
+ @ValidateOnExecution
+ public static class ValidateExecutableMixedNone {
+
+ @POST
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public Integer validateExecutable(@Max(10) final Integer value) {
+ return value;
+ }
+ }
+
+ /**
+ * GETTERS.
+ */
+
+ public abstract static class ValidateGetterExecutable {
+
+ @GET
+ @Path("sanity")
+ public String getSanity() {
+ return "ok";
+ }
+ }
+
+ @Path("getter-on-method-default")
+ public static class ValidateGetterExecutableOnMethodDefault extends ValidateGetterExecutable {
+
+ @GET
+ @ValidateOnExecution
+ @NotNull
+ public String getDefault() {
+ return null;
+ }
+ }
+
+ @Path("getter-on-method-miss")
+ public static class ValidateGetterExecutableOnMethodMiss extends ValidateGetterExecutable {
+
+ @GET
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ @NotNull
+ public String getMiss() {
+ return null;
+ }
+ }
+
+ @Path("getter-on-method-match")
+ public static class ValidateGetterExecutableOnMethodMatch extends ValidateGetterExecutable {
+
+ @GET
+ @ValidateOnExecution(type = {ExecutableType.NON_GETTER_METHODS, ExecutableType.GETTER_METHODS})
+ @NotNull
+ public String getMatch() {
+ return null;
+ }
+ }
+
+ @Path("getter-on-type-default")
+ @ValidateOnExecution
+ public static class ValidateGetterExecutableOnTypeDefault extends ValidateGetterExecutable {
+
+ @GET
+ @NotNull
+ public String getDefault() {
+ return null;
+ }
+ }
+
+ @Path("getter-on-type-miss")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static class ValidateGetterExecutableOnTypeMiss extends ValidateGetterExecutable {
+
+ @GET
+ @NotNull
+ public String getMiss() {
+ return null;
+ }
+ }
+
+ @Path("getter-on-type-match")
+ @ValidateOnExecution(type = {ExecutableType.NON_GETTER_METHODS, ExecutableType.GETTER_METHODS})
+ public static class ValidateGetterExecutableOnTypeMatch extends ValidateGetterExecutable {
+
+ @GET
+ @NotNull
+ public String getMatch() {
+ return null;
+ }
+ }
+
+ /**
+ * BEANS.
+ */
+
+ @Path("getter-on-beans")
+ public static class ValidateGetterExecutableOnBeans {
+
+ @POST
+ @Valid
+ public AnotherContactBean post(@Valid final AnotherContactBean bean) {
+ return bean;
+ }
+
+ @POST
+ @Path("invalidMail")
+ @Valid
+ public AnotherContactBean invalidMail(@Valid final AnotherContactBean bean) {
+ bean.setEmail("ab");
+ return bean;
+ }
+
+ @POST
+ @Path("invalidPhone")
+ @Valid
+ public AnotherContactBean invalidPhone(@Valid final AnotherContactBean bean) {
+ bean.setPhone("12");
+ return bean;
+ }
+ }
+
+ @Path("getter-resource-method")
+ @Singleton
+ public static class ValidateGetterResourceMethod {
+
+ private int count = 1;
+
+ @GET
+ @Max(1)
+ public int getValue() {
+ return count++;
+ }
+ }
+
+ @Path("on-type-getter-null")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static class ValidateExecutableResource {
+
+ @Path("nogetter")
+ @GET
+ @NotNull
+ public String daNull() {
+ return null;
+ }
+
+ @Path("getter")
+ @GET
+ @NotNull
+ public String getNull() {
+ return null;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return new ResourceConfig(ValidateExecutableOnMethodsResource.class,
+ ValidateExecutableOnTypeDefault.class,
+ ValidateExecutableOnTypeMatch.class,
+ ValidateExecutableOnTypeMiss.class,
+ ValidateExecutableOnTypeNone.class,
+ ValidateExecutableMixedDefault.class,
+ ValidateExecutableMixedNone.class,
+ ValidateGetterExecutableOnMethodDefault.class,
+ ValidateGetterExecutableOnMethodMiss.class,
+ ValidateGetterExecutableOnMethodMatch.class,
+ ValidateGetterExecutableOnTypeDefault.class,
+ ValidateGetterExecutableOnTypeMiss.class,
+ ValidateGetterExecutableOnTypeMatch.class,
+ ValidateGetterExecutableOnBeans.class,
+ ValidateGetterResourceMethod.class,
+ ValidateExecutableResource.class)
+ .property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
+ }
+
+ @Test
+ public void testOnTypeValidateInputFailValidateExecutableDefault() throws Exception {
+ _testOnType("default", 15, 400);
+ }
+
+ @Test
+ @RunSeparately
+ public void testOnTypeValidateResultFailValidateExecutableDefault() throws Exception {
+ _testOnType("default", -15, 500);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassBiggerValidateExecutableMiss() throws Exception {
+ _testOnType("miss", 15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassBiggerValidateExecutableNone() throws Exception {
+ _testOnType("none", 15, 200);
+ }
+
+ @Test
+ public void testOnMethodGetterDefault() throws Exception {
+ final WebTarget target = target("getter-on-method-default");
+
+ assertThat(target.request().get().getStatus(), equalTo(400));
+ assertThat(target.path("sanity").request().get().getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testOnMethodGetterMiss() throws Exception {
+ final WebTarget target = target("getter-on-method-miss");
+
+ Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(400));
+
+ response = target.path("sanity").request().get();
+ assertThat(response.getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testOnMethodGetterMatch() throws Exception {
+ final WebTarget target = target("getter-on-method-match");
+
+ assertThat(target.request().get().getStatus(), equalTo(400));
+ assertThat(target.path("sanity").request().get().getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testOnTypeGetterDefault() throws Exception {
+ final WebTarget target = target("getter-on-type-default");
+
+ assertThat(target.request().get().getStatus(), equalTo(400));
+ assertThat(target.path("sanity").request().get().getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testOnTypeGetterMiss() throws Exception {
+ final WebTarget target = target("getter-on-type-miss");
+
+ Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(400));
+
+ response = target.path("sanity").request().get();
+ assertThat(response.getStatus(), equalTo(400));
+ }
+
+ /**
+ * Validation should fail when getter (also a resource method) is invoked and not when the resource class is validated.
+ */
+ @Test
+ public void testGetterResourceMethod() throws Exception {
+ final WebTarget target = target("getter-resource-method");
+ final Response response = target.request().get();
+
+ assertThat(response.getStatus(), equalTo(500));
+ }
+
+ @Test
+ public void testOnTypeGetterNull() throws Exception {
+ final WebTarget target = target("on-type-getter-null");
+
+ Response response = target.path("nogetter").request().get();
+ assertThat(response.getStatus(), equalTo(400));
+
+ response = target.path("getter").request().get();
+ assertThat(response.getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testOnTypeGetterMatch() throws Exception {
+ final WebTarget target = target("getter-on-type-match");
+
+ assertThat(target.request().get().getStatus(), equalTo(400));
+ assertThat(target.path("sanity").request().get().getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testBeansPositive() throws Exception {
+ final WebTarget target = target("getter-on-beans");
+ final AnotherContactBean contactBean = new AnotherContactBean("jersey@example.com", null, "Jersey JAX-RS", null);
+
+ final Response response = target.request().post(Entity.xml(contactBean));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(AnotherContactBean.class), equalTo(contactBean));
+ }
+
+ @Test
+ public void testBeansValidateGetterInvalidEmail() throws Exception {
+ final WebTarget target = target("getter-on-beans");
+ final AnotherContactBean contactBean = new AnotherContactBean("jersey", null, "Jersey JAX-RS", null);
+
+ final Response response = target.request().post(Entity.xml(contactBean));
+
+ assertThat(response.getStatus(), equalTo(400));
+ }
+
+ @Test
+ public void testBeansValidateGetterInvalidPhone() throws Exception {
+ final WebTarget target = target("getter-on-beans");
+ final AnotherContactBean contactBean = new AnotherContactBean("jersey@example.com", "12", "Jersey JAX-RS", null);
+
+ final Response response = target.request().post(Entity.xml(contactBean));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(AnotherContactBean.class), equalTo(contactBean));
+ }
+
+ @Test
+ public void testBeansValidateGetterInvalidReturnMail() throws Exception {
+ final WebTarget target = target("getter-on-beans").path("invalidMail");
+ final AnotherContactBean contactBean = new AnotherContactBean("jersey@example.com", null, "Jersey JAX-RS", null);
+
+ final Response response = target.request().post(Entity.xml(contactBean));
+
+ assertThat(response.getStatus(), equalTo(500));
+ }
+
+ @Test
+ public void testBeansValidateGetterInvalidReturnPhone() throws Exception {
+ final WebTarget target = target("getter-on-beans").path("invalidPhone");
+ final AnotherContactBean contactBean = new AnotherContactBean("jersey@example.com", null, "Jersey JAX-RS", null);
+
+ final Response response = target.request().post(Entity.xml(contactBean));
+ contactBean.setPhone("12");
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(AnotherContactBean.class), equalTo(contactBean));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceGenericsTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceGenericsTest.java
new file mode 100644
index 0000000..662bfd4
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceGenericsTest.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Michal Gajdos
+ */
+// @RunWith(ConcurrentRunner.class)
+public class ValidateOnExecutionInheritanceGenericsTest extends ValidateOnExecutionAbstractTest {
+
+ /**
+ * On METHOD.
+ */
+
+ /**
+ * {@link ValidateOnExecution} annotations from this interface should be considered during validating phase.
+ */
+ @SuppressWarnings({"UnusedDeclaration", "JavaDoc"})
+ public static interface ValidateExecutableOnMethodsValidation<T extends Number> {
+
+ @Min(0)
+ @ValidateOnExecution
+ public T validateExecutableDefault(@Max(10) final T value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public T validateExecutableMatch(@Max(10) final T value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public T validateExecutableMiss(@Max(10) final T value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public T validateExecutableNone(@Max(10) final T value);
+ }
+
+ /**
+ * Wrong generic types. {@link ValidateOnExecution} annotations should not be considered at all.
+ *
+ * @param <T>
+ */
+ @SuppressWarnings({"UnusedDeclaration", "JavaDoc"})
+ public static interface ValidateExecutableOnMethodsCharSequenceValidation<T extends CharSequence> {
+
+ @Min(10)
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public T validateExecutableDefault(@Max(0) final T value);
+
+ @Min(10)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public T validateExecutableMatch(@Max(0) final T value);
+
+ @Min(10)
+ @ValidateOnExecution
+ public T validateExecutableMiss(@Max(0) final T value);
+
+ @Min(10)
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public T validateExecutableNone(@Max(0) final T value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public static interface ValidateExecutableOnMethodsJaxRs extends ValidateExecutableOnMethodsValidation<Integer> {
+
+ @POST
+ @Path("validateExecutableDefault")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ Integer validateExecutableDefault(final Integer value);
+
+ @POST
+ @Path("validateExecutableMatch")
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ Integer validateExecutableMatch(final Integer value);
+
+ @POST
+ @Path("validateExecutableMiss")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ Integer validateExecutableMiss(final Integer value);
+
+ @POST
+ @Path("validateExecutableNone")
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ Integer validateExecutableNone(final Integer value);
+ }
+
+ public abstract static class ValidateExecutableOnMethodsAbstractResource
+ implements ValidateExecutableOnMethodsJaxRs, ValidateExecutableOnMethodsCharSequenceValidation<String> {
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public abstract Integer validateExecutableDefault(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public abstract Integer validateExecutableMatch(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public abstract Integer validateExecutableMiss(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public abstract Integer validateExecutableNone(final Integer value);
+ }
+
+ @Path("on-method")
+ public static class ValidateExecutableOnMethodsResource extends ValidateExecutableOnMethodsAbstractResource {
+
+ public Integer validateExecutableDefault(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableMatch(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableMiss(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableNone(final Integer value) {
+ return value;
+ }
+
+ public String validateExecutableDefault(final String value) {
+ return value;
+ }
+
+ public String validateExecutableMatch(final String value) {
+ return value;
+ }
+
+ public String validateExecutableMiss(final String value) {
+ return value;
+ }
+
+ public String validateExecutableNone(final String value) {
+ return value;
+ }
+ }
+
+ /**
+ * On TYPE.
+ */
+
+ @SuppressWarnings("JavaDoc")
+ public static interface ValidateExecutableOnType<T extends Number> {
+
+ @Min(0)
+ public T validateExecutable(@Max(10) final T value);
+ }
+
+ @SuppressWarnings("JavaDoc")
+ public static interface ValidateExecutableCharSequenceOnType<X extends CharSequence> {
+
+ @Min(10)
+ public X validateExecutable(@Max(0) final X value);
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableOnTypeDefault extends ValidateExecutableOnType<Integer> {
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableCharSequenceOnTypeDefault extends ValidateExecutableCharSequenceOnType<String> {
+
+ @ValidateOnExecution
+ public String validateExecutable(final String value);
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeDefaultAbstractResource implements ValidateExecutableOnTypeDefault {
+
+ @POST
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-default")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public static class ValidateExecutableOnTypeDefaultResource extends ValidateExecutableOnTypeDefaultAbstractResource
+ implements ValidateExecutableCharSequenceOnTypeDefault {
+
+ @POST
+ @Path("another")
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static interface ValidateExecutableOnTypeMatch extends ValidateExecutableOnType<Integer> {
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableCharSequenceOnTypeMatch extends ValidateExecutableCharSequenceOnType<String> {
+
+ @ValidateOnExecution
+ public String validateExecutable(final String value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeMatchAbstractResource implements ValidateExecutableOnTypeMatch {
+
+ @POST
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-match")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static class ValidateExecutableOnTypeMatchResource extends ValidateExecutableOnTypeMatchAbstractResource
+ implements ValidateExecutableCharSequenceOnTypeMatch {
+
+ @POST
+ @Path("another")
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public static interface ValidateExecutableOnTypeMiss extends ValidateExecutableOnType<Integer> {
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableCharSequenceOnTypeMiss extends ValidateExecutableCharSequenceOnType<String> {
+
+ @ValidateOnExecution
+ public String validateExecutable(final String value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeMissAbstractResource implements ValidateExecutableOnTypeMiss {
+
+ @POST
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-miss")
+ @ValidateOnExecution
+ public static class ValidateExecutableOnTypeMissResource extends ValidateExecutableOnTypeMissAbstractResource
+ implements ValidateExecutableCharSequenceOnTypeMiss {
+
+ @POST
+ @Path("another")
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableOnTypeNone extends ValidateExecutableOnType<Integer> {
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableCharSequenceOnTypeNone extends ValidateExecutableCharSequenceOnType<String> {
+
+ @ValidateOnExecution
+ public String validateExecutable(final String value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public abstract static class ValidateExecutableOnTypeNoneAbstractResource implements ValidateExecutableOnTypeNone {
+
+ @POST
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-none")
+ @ValidateOnExecution(type = {ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS})
+ public static class ValidateExecutableOnTypeNoneResource extends ValidateExecutableOnTypeNoneAbstractResource
+ implements ValidateExecutableCharSequenceOnTypeNone {
+
+ @POST
+ @Path("another")
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ /**
+ * MIXED.
+ */
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableMixedDefault<T extends Number> {
+
+ @Min(0)
+ @ValidateOnExecution
+ public T validateExecutable(@Max(10) final T value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableCharSequenceMixedDefault<T extends CharSequence> {
+
+ @Min(10)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public T validateExecutable(@Max(0) final T value);
+ }
+
+ @Path("mixed-default")
+ public static class ValidateExecutableMixedDefaultResource
+ implements ValidateExecutableMixedDefault<Integer>, ValidateExecutableCharSequenceMixedDefault<String> {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("another")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableMixedNone<T extends Number> {
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public T validateExecutable(@Max(10) final T value);
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableCharSequenceMixedNone<T extends CharSequence> {
+
+ @Min(10)
+ @ValidateOnExecution
+ public T validateExecutable(@Max(0) final T value);
+ }
+
+ @Path("mixed-none")
+ public static class ValidateExecutableMixedNoneResource
+ implements ValidateExecutableMixedNone<Integer>, ValidateExecutableCharSequenceMixedNone<String> {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+
+ @POST
+ @Path("another")
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public String validateExecutable(final String value) {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ValidateExecutableOnMethodsResource.class,
+ ValidateExecutableOnTypeDefaultResource.class,
+ ValidateExecutableOnTypeMatchResource.class,
+ ValidateExecutableOnTypeMissResource.class,
+ ValidateExecutableOnTypeNoneResource.class,
+ ValidateExecutableMixedDefaultResource.class,
+ ValidateExecutableMixedNoneResource.class)
+ .property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableDefault() throws Exception {
+ _testOnType("default", 15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassNoValidateExecutableDefault() throws Exception {
+ _testOnType("default", -15, 200);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceTest.java
new file mode 100644
index 0000000..b606a66
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionInheritanceTest.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+import org.junit.Test;
+
+/**
+ * @author Michal Gajdos
+ */
+// @RunWith(ConcurrentRunner.class)
+public class ValidateOnExecutionInheritanceTest extends ValidateOnExecutionAbstractTest {
+
+ /**
+ * On METHOD.
+ */
+
+ /**
+ * {@link ValidateOnExecution} annotations from this interface should be considered during validating phase.
+ */
+ @SuppressWarnings({"UnusedDeclaration", "JavaDoc"})
+ public static interface ValidateExecutableOnMethodsValidation {
+
+ @Min(0)
+ @ValidateOnExecution
+ public Integer validateExecutableDefault(@Max(10) final Integer value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public Integer validateExecutableMatch(@Max(10) final Integer value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public Integer validateExecutableMiss(@Max(10) final Integer value);
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public Integer validateExecutableNone(@Max(10) final Integer value);
+ }
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public static interface ValidateExecutableOnMethodsJaxRs extends ValidateExecutableOnMethodsValidation {
+
+ @POST
+ @Path("validateExecutableDefault")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ Integer validateExecutableDefault(final Integer value);
+
+ @POST
+ @Path("validateExecutableMatch")
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ Integer validateExecutableMatch(final Integer value);
+
+ @POST
+ @Path("validateExecutableMiss")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ Integer validateExecutableMiss(final Integer value);
+
+ @POST
+ @Path("validateExecutableNone")
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ Integer validateExecutableNone(final Integer value);
+ }
+
+ public abstract static class ValidateExecutableOnMethodsAbstractResource implements ValidateExecutableOnMethodsJaxRs {
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public abstract Integer validateExecutableDefault(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public abstract Integer validateExecutableMatch(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public abstract Integer validateExecutableMiss(final Integer value);
+
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public abstract Integer validateExecutableNone(final Integer value);
+ }
+
+ @Path("on-method")
+ public static class ValidateExecutableOnMethodsResource extends ValidateExecutableOnMethodsAbstractResource {
+
+ public Integer validateExecutableDefault(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableMatch(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableMiss(final Integer value) {
+ return value;
+ }
+
+ public Integer validateExecutableNone(final Integer value) {
+ return value;
+ }
+ }
+
+ /**
+ * On TYPE.
+ */
+
+ @SuppressWarnings("JavaDoc")
+ public static interface ValidateExecutableOnType {
+
+ @POST
+ @Min(0)
+ public Integer validateExecutable(@Max(10) final Integer value);
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableOnTypeDefault extends ValidateExecutableOnType {
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeDefaultAbstractResource implements ValidateExecutableOnTypeDefault {
+
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-default")
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public static class ValidateExecutableOnTypeDefaultResource extends ValidateExecutableOnTypeDefaultAbstractResource {
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static interface ValidateExecutableOnTypeMatch extends ValidateExecutableOnType {
+ }
+
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeMatchAbstractResource implements ValidateExecutableOnTypeMatch {
+
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-match")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static class ValidateExecutableOnTypeMatchResource extends ValidateExecutableOnTypeMatchAbstractResource {
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public static interface ValidateExecutableOnTypeMiss extends ValidateExecutableOnType {
+ }
+
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public abstract static class ValidateExecutableOnTypeMissAbstractResource implements ValidateExecutableOnTypeMiss {
+
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-miss")
+ @ValidateOnExecution
+ public static class ValidateExecutableOnTypeMissResource extends ValidateExecutableOnTypeMissAbstractResource {
+ }
+
+ /**
+ * This {@link ValidateOnExecution} annotation should be considered during validating phase.
+ */
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableOnTypeNone extends ValidateExecutableOnType {
+ }
+
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public abstract static class ValidateExecutableOnTypeNoneAbstractResource implements ValidateExecutableOnTypeNone {
+
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Path("on-type-none")
+ @ValidateOnExecution(type = {ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS})
+ public static class ValidateExecutableOnTypeNoneResource extends ValidateExecutableOnTypeNoneAbstractResource {
+ }
+
+ /**
+ * MIXED.
+ */
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableMixedDefault {
+
+ @Min(0)
+ @ValidateOnExecution
+ public Integer validateExecutable(@Max(10) final Integer value);
+ }
+
+ @Path("mixed-default")
+ public static class ValidateExecutableMixedDefaultResource implements ValidateExecutableMixedDefault {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableMixedNone {
+
+ @Min(0)
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public Integer validateExecutable(@Max(10) final Integer value);
+ }
+
+ @Path("mixed-none")
+ public static class ValidateExecutableMixedNoneResource implements ValidateExecutableMixedNone {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @ValidateOnExecution
+ public static interface ValidateExecutableMixedClassDefault {
+
+ @Min(0)
+ public Integer validateExecutable(@Max(10) final Integer value);
+ }
+
+ @Path("mixed-class-default")
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static class ValidateExecutableMixedClassDefaultResource implements ValidateExecutableMixedClassDefault {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.CONSTRUCTORS)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @ValidateOnExecution(type = ExecutableType.NONE)
+ public static interface ValidateExecutableMixedClassNone {
+
+ @Min(0)
+ public Integer validateExecutable(@Max(10) final Integer value);
+ }
+
+ @Path("mixed-class-none")
+ @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)
+ public static class ValidateExecutableMixedClassNoneResource implements ValidateExecutableMixedClassNone {
+
+ @POST
+ @ValidateOnExecution(type = ExecutableType.ALL)
+ public Integer validateExecutable(final Integer value) {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ValidateExecutableOnMethodsResource.class,
+ ValidateExecutableOnTypeNoneResource.class,
+ ValidateExecutableOnTypeMissResource.class,
+ ValidateExecutableOnTypeMatchResource.class,
+ ValidateExecutableOnTypeDefaultResource.class,
+ ValidateExecutableMixedDefaultResource.class,
+ ValidateExecutableMixedNoneResource.class,
+ ValidateExecutableMixedClassNoneResource.class,
+ ValidateExecutableMixedClassDefaultResource.class)
+ .property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
+ }
+
+ @Test
+ public void testOnTypeValidateInputPassValidateExecutableDefault() throws Exception {
+ _testOnType("default", 15, 200);
+ }
+
+ @Test
+ public void testOnTypeValidateResultPassNoValidateExecutableDefault() throws Exception {
+ _testOnType("default", -15, 200);
+ }
+
+ @Test
+ public void testMixedClassValidatePassDefault() throws Exception {
+ _test("mixed-class-default", 0, 200);
+ }
+
+ @Test
+ public void testMixedClassValidateInputPassValidateDefault() throws Exception {
+ _test("mixed-class-default", 15, 200);
+ }
+
+ @Test
+ public void testMixedClassValidateResultPassNoValidateDefault() throws Exception {
+ _test("mixed-class-default", -15, 200);
+ }
+
+ @Test
+ public void testMixedClassValidatePassNone() throws Exception {
+ _test("mixed-class-none", 0, 200);
+ }
+
+ @Test
+ public void testMixedClassValidateInputPassNone() throws Exception {
+ _test("mixed-class-none", 15, 200);
+ }
+
+ @Test
+ public void testMixedClassValidateResultPassNone() throws Exception {
+ _test("mixed-class-none", -15, 200);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java
new file mode 100644
index 0000000..6c54c42
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.validation.validateonexecution;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import javax.validation.ValidationException;
+import javax.validation.constraints.NotNull;
+import javax.validation.executable.ExecutableType;
+import javax.validation.executable.ValidateOnExecution;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Testing whether an {@link javax.validation.ValidationException} is raised when {@link ValidateOnExecution} is present on
+ * overriding/implementing method as well.
+ *
+ * @author Michal Gajdos
+ */
+public class ValidateOnExecutionOverrideTest extends JerseyTest {
+
+ public static interface Validation {
+
+ @NotNull
+ @ValidateOnExecution
+ public String interfaceMessage();
+ }
+
+ public abstract static class ValidationBase {
+
+ @NotNull
+ @ValidateOnExecution
+ public abstract String classMessage();
+ }
+
+ @Path("/")
+ public static class ValidationResource extends ValidationBase implements Validation {
+
+ @GET
+ @Path("interface")
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public String interfaceMessage() {
+ return "ko";
+ }
+
+ @GET
+ @Path("class")
+ @ValidateOnExecution(type = ExecutableType.GETTER_METHODS)
+ public String classMessage() {
+ return "ko";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+
+ return new ResourceConfig(ValidationResource.class);
+ }
+
+ @Test
+ public void testOverridingCheckOnInterface() throws Exception {
+ _test("interface");
+ }
+
+ @Test
+ public void testOverridingCheckOnClass() throws Exception {
+ _test("class");
+ }
+
+ private void _test(final String path) throws Exception {
+ assertThat(target(path).request().get().getStatus(), equalTo(500));
+
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ assertThat(loggedRecords.size(), equalTo(1));
+ assertThat(loggedRecords.get(0).getThrown(), instanceOf(ValidationException.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/OverrideWadlResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/OverrideWadlResourceTest.java
new file mode 100644
index 0000000..4b38262
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/OverrideWadlResourceTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.wadl;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * @author Paul Sandoz
+ */
+public class OverrideWadlResourceTest extends JerseyTest {
+
+ // The explicit @Produces definition improves the compatibility of the test case with other connectors.
+ // Unlike HttpUrlConnector, others might not be sending default accepted media types ((namely the JdkConnector)
+ // and the resource would not be matched.
+ @Produces("text/plain")
+ @Path("application.wadl")
+ public static class OverrideWadlApplicationResource {
+ @GET
+ public String get() {
+ return "OVERRIDE";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(OverrideWadlApplicationResource.class);
+ }
+
+ @Test
+ public void testOverride() {
+ WebTarget target = target("/application.wadl");
+
+ assertEquals("OVERRIDE", target.request().get(String.class));
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/ResourceExtendedFlagTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/ResourceExtendedFlagTest.java
new file mode 100644
index 0000000..3da5917
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/ResourceExtendedFlagTest.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.wadl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.internal.util.SaxHelper;
+import org.glassfish.jersey.internal.util.SimpleNamespaceResolver;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.server.ExtendedResourceContext;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.ExtendedResource;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceMethod;
+import org.glassfish.jersey.server.model.ResourceModel;
+import org.glassfish.jersey.server.wadl.internal.WadlUtils;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test verifies functionality of {@link org.glassfish.jersey.server.model.Resource#isExtended()} and its
+ * influence on WADL.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ResourceExtendedFlagTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class, AllExtended.class, LoggingFeature.class);
+ }
+
+ @Path("all-extended")
+ public static class AllExtended {
+
+ @GET
+ @ExtendedResource
+ public String allExtendedGet() {
+ return "get";
+ }
+
+ @GET
+ @Path("sub")
+ @ExtendedResource
+ public String allExtendedSubGet() {
+ return "sub-get";
+ }
+
+ @Path("locator")
+ @ExtendedResource
+ public SubResourceLocator allExtendedSubLocator() {
+ return new SubResourceLocator();
+ }
+ }
+
+ public static class SubResourceLocator {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @Context
+ private ExtendedResourceContext extendedResourceContext;
+
+ @GET
+ public String resourceGet() {
+
+ final String error = validateModel();
+ return error == null ? "ok" : error;
+ }
+
+ @GET
+ @Path("extended")
+ @ExtendedResource
+ public String resourceExtendedGet() {
+ return "extended";
+ }
+
+ @POST
+ @ExtendedResource
+ public String resourceExtendedPost() {
+ return "extendedpost";
+ }
+
+ @POST
+ @Path("visible")
+ public String resourceVisiblePost() {
+ return "visiblepost";
+ }
+
+ private String validateModel() {
+ Map<String, Boolean> extendedMethods = new HashMap<>();
+ extendedMethods.put("resourceExtendedGet", false);
+ extendedMethods.put("resourceExtendedPost", false);
+ extendedMethods.put("allExtendedGet", false);
+ extendedMethods.put("allExtendedSubGet", false);
+ extendedMethods.put("allExtendedSubLocator", false);
+
+ Map<String, Boolean> visibleMethods = new HashMap<>();
+ visibleMethods.put("resourceVisiblePost", false);
+ visibleMethods.put("resourceGet", false);
+
+ final ResourceModel resourceModel = extendedResourceContext.getResourceModel();
+ for (Resource rootResource : resourceModel.getRootResources()) {
+ final String error = checkResource(rootResource, extendedMethods, visibleMethods, "");
+ if (error != null) {
+ return error;
+ }
+ }
+
+ for (Map.Entry<String, Boolean> entry : extendedMethods.entrySet()) {
+ if (entry.getValue() != null && !entry.getValue()) {
+ return "Extended method " + entry.getKey() + " was not found";
+ }
+ }
+
+ for (Map.Entry<String, Boolean> entry : visibleMethods.entrySet()) {
+ if (entry.getValue() != null && !entry.getValue()) {
+ return "Visible method " + entry.getKey() + " was not found";
+ }
+ }
+ return null;
+ }
+
+ private String checkResource(Resource resource, Map<String, Boolean> extendedMethods,
+ Map<String, Boolean> visibleMethods, String prefix) {
+
+ System.out.println(prefix + "R extended=" + resource.isExtended() + " resource: " + resource);
+
+ boolean allExtended = true;
+ for (ResourceMethod resourceMethod : resource.getAllMethods()) {
+ if ("OPTIONS".equals(resourceMethod.getHttpMethod()) && !resourceMethod.isExtended()) {
+ return "OPTIONS method " + resourceMethod + " is not extended";
+ }
+ if (!resourceMethod.isExtended()) {
+ allExtended = false;
+ }
+
+ final String methodName = resourceMethod.getInvocable().getHandlingMethod().getName();
+ if (extendedMethods.get(methodName) != null) {
+ extendedMethods.put(methodName, true);
+ if (!resourceMethod.isExtended()) {
+ return "Method " + methodName + " should be extended.";
+ }
+ }
+
+ if (visibleMethods.get(methodName) != null) {
+ visibleMethods.put(methodName, true);
+ if (resourceMethod.isExtended()) {
+ return "Method " + methodName + " should NOT be extended.";
+ }
+ }
+ System.out.println(prefix + " M extended=" + resourceMethod.isExtended() + " method: " + methodName);
+ }
+
+ for (Resource child : resource.getChildResources()) {
+ final String error = checkResource(child, extendedMethods, visibleMethods, " ");
+ if (error != null) {
+ return error;
+ }
+ }
+
+ if (allExtended != resource.isExtended()) {
+ return "Resource " + resource + "Resource.extended = " + resource.isExtended() + " and allExtended="
+ + allExtended;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Invokes resource method which goes trough the {@link org.glassfish.jersey.server.model.ResourceModel}
+ * and checks whether {@code extended} flag is correctly defined on resources and methods.
+ */
+ @Test
+ public void testResourceModel() {
+ final Response response = target().path("resource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("ok", response.readEntity(String.class));
+ }
+
+ /**
+ * Tests full wadl with all "extended" details.
+ *
+ * @throws ParserConfigurationException
+ * @throws XPathExpressionException
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testDetailedWadl() throws ParserConfigurationException, XPathExpressionException, IOException,
+ SAXException {
+ Response response = target("/application.wadl").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request(MediaTypes.WADL_TYPE).get();
+ assertEquals(200, response.getStatus());
+ File tmpFile = response.readEntity(File.class);
+ DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ DocumentBuilder b = bf.newDocumentBuilder();
+ Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ // check base URI
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 8
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("8", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='all-extended'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='resource'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='application.wadl'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+
+ xp.setNamespaceContext(new SimpleNamespaceResolver("jersey", "http://jersey.java.net/"));
+ val = (String) xp.evaluate("count(//jersey:extended)", d, XPathConstants.STRING);
+ assertEquals("31", val);
+ }
+
+ /**
+ * Tests limited wadl with only user resources.
+ *
+ * @throws ParserConfigurationException
+ * @throws XPathExpressionException
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testLimitedWadl() throws ParserConfigurationException, XPathExpressionException, IOException,
+ SAXException {
+ Response response = target("/application.wadl").request(MediaTypes.WADL_TYPE).get();
+ assertEquals(200, response.getStatus());
+ File tmpFile = response.readEntity(File.class);
+ DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ DocumentBuilder b = bf.newDocumentBuilder();
+ Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ // check base URI
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 8
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("2", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='all-extended'])", d, XPathConstants.STRING);
+ assertEquals("0", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='resource'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+
+ val = (String) xp.evaluate("count(//wadl:resource[@path='application.wadl'])", d, XPathConstants.STRING);
+ assertEquals("0", val);
+
+ xp.setNamespaceContext(new SimpleNamespaceResolver("jersey", "http://jersey.java.net/"));
+ val = (String) xp.evaluate("count(//jersey:extended)", d, XPathConstants.STRING);
+ assertEquals("0", val);
+ }
+
+ public static void printSource(Source source) {
+ try {
+ System.out.println("---------------------");
+ Transformer trans = TransformerFactory.newInstance().newTransformer();
+ Properties oprops = new Properties();
+ oprops.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ oprops.put(OutputKeys.INDENT, "yes");
+ oprops.put(OutputKeys.METHOD, "xml");
+ trans.setOutputProperties(oprops);
+ trans.transform(source, new StreamResult(System.out));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java
new file mode 100644
index 0000000..d2df87e
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.wadl;
+
+import java.io.StringWriter;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.internal.util.SimpleNamespaceResolver;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.ElementNameAndTextQualifier;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests whether WADL for a {@link BeanParam} annotated resource method parameter is generated properly.
+ * <p/>
+ * The tests of this class perform a comparison of
+ * <pre><ul>
+ * <li>a WADL of a reference resource that has {@code *Param} annotated class fields or resource method parameters</li>
+ * <li>with a resource configured with {@link BeanParam} annotated parameters where some of the reference resource parameters
+ * are aggregated in the class that is used as a bean param</li>
+ * </ul></pre>
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class WadlBeanParamTest extends JerseyTest {
+
+ private final ElementNameAndTextQualifier elementQualifier = new ElementNameAndTextQualifier() {
+
+ /**
+ * For {@code <param ??? />} nodes, the comparison is based on matching {@code name} attributes while ignoring
+ * their order. For any other nodes, strict comparison (including ordering) is made.
+ *
+ * @param control The reference element to compare the {@code test} with.
+ * @param test The test element to compare against {@code control}.
+ * @return Whether given nodes qualify for comparison.
+ */
+ @Override
+ public boolean qualifyForComparison(final Element control, final Element test) {
+ if (test != null && !"param".equals(test.getNodeName())) {
+ return super.qualifyForComparison(control, test);
+ }
+ if (!(control != null && test != null
+ && equalsNamespace(control, test)
+ && getNonNamespacedNodeName(control).equals(getNonNamespacedNodeName(test)))) {
+ return false;
+ }
+ if (control.hasAttribute("name") && test.hasAttribute("name")) {
+ if (control.getAttribute("name").equals(test.getAttribute("name"))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ReferenceResourceBeanParam.class, TestResourceBeanParam.class,
+ TestResourceConstructorInitializedBeanParam.class, TestResourceFieldBeanParam.class);
+ }
+
+ private String nodeAsString(final Object resourceNode) throws TransformerException {
+ StringWriter writer = new StringWriter();
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.transform(new DOMSource((Node) resourceNode), new StreamResult(writer));
+ return writer.toString();
+ }
+
+ /**
+ * Tests whether class with {@code *Param} annotated fields if used as a {@code BeanParam} annotated resource method parameter
+ * results in a correctly generated WADL.
+ *
+ * @throws Exception In case of any problem.
+ */
+ @Test
+ public void testBeanParamFullBean() throws Exception {
+ testBeanParamConstructorInitializedBean("wadlBeanParamTest");
+ }
+
+ /**
+ * Tests whether class with {@code *Param} annotated constructor parameters if used as a {@code BeanParam} annotated resource
+ * method parameter results in a correctly generated WADL.
+ *
+ * @throws Exception In case of any problem.
+ */
+ @Test
+ public void testBeanParamConstructorInitializedBean() throws Exception {
+ testBeanParamConstructorInitializedBean("wadlBeanParamConstructorInitializedTest");
+ }
+
+ /**
+ * Tests whether class with {@code *Param} annotated constructor parameters if used as a {@code BeanParam} annotated resource
+ * class field parameter results in a correctly generated WADL.
+ *
+ * @throws Exception In case of any problem.
+ */
+ @Test
+ public void testBeanParamFieldBean() throws Exception {
+ testBeanParamConstructorInitializedBean("wadlBeanParamFieldTest");
+ }
+
+ private void testBeanParamConstructorInitializedBean(String resource) throws Exception {
+ final Response response = target("/application.wadl").request().get();
+ final Document d = WadlResourceTest.extractWadlAsDocument(response);
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ final SimpleNamespaceResolver nsContext = new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02");
+ xp.setNamespaceContext(nsContext);
+
+ final Diff diff = XMLUnit.compareXML(
+ nodeAsString(
+ xp.evaluate("//wadl:resource[@path='wadlBeanParamReference']/wadl:resource", d,
+ XPathConstants.NODE)),
+ nodeAsString(
+ xp.evaluate("//wadl:resource[@path='" + resource + "']/wadl:resource", d,
+ XPathConstants.NODE))
+ );
+ XMLUnit.setXpathNamespaceContext(
+ new SimpleNamespaceContext(ImmutableMap.of("wadl", "http://wadl.dev.java.net/2009/02")));
+ diff.overrideElementQualifier(elementQualifier);
+ XMLAssert.assertXMLEqual(diff, true);
+ }
+
+ @Path("wadlBeanParamReference")
+ private static class ReferenceResourceBeanParam {
+
+ @QueryParam("classFieldQueryParam")
+ private String classFieldQueryParam;
+
+ //////////////////////////////////////////////////////////////////
+ // following fields make this class compatible with 'FullBean', //
+ // 'ConstructorInitializedBean' and 'SmallBean' //
+ @HeaderParam("header")
+ private String headerParam;
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @Encoded
+ @QueryParam("query")
+ private String queryParam;
+
+ @CookieParam("cookie")
+ private String cookie;
+
+ @FormParam("form")
+ private String formParam;
+
+ @POST
+ @Path("singleBean/{path}")
+ public String postBeanParam(/* pathParam is also extracted from FullBean */
+ @PathParam("path") String pathParam,
+ @QueryParam("methodParam") int methodParam,
+ @HeaderParam("header") String duplicateHeaderParam) {
+ return "";
+ }
+
+ }
+
+ @Path("wadlBeanParamTest")
+ private static class TestResourceBeanParam {
+
+ @QueryParam("classFieldQueryParam")
+ private String classFieldQueryParam;
+
+ @POST
+ @Path("singleBean/{path}")
+ public String postBeanParam(@BeanParam WadlFullBean bean,
+ @BeanParam WadlSmallBean wadlSmallBean,
+ @QueryParam("methodParam") int methodParam) {
+ return "";
+ }
+
+ }
+
+ @Path("wadlBeanParamConstructorInitializedTest")
+ private static class TestResourceConstructorInitializedBeanParam {
+
+ @QueryParam("classFieldQueryParam")
+ private String classFieldQueryParam;
+
+ @POST
+ @Path("singleBean/{path}")
+ public String postBeanParam(@BeanParam WadlConstructorInitializedBean bean,
+ @BeanParam WadlSmallBean wadlSmallBean,
+ @QueryParam("methodParam") int methodParam) {
+ return "";
+ }
+
+ }
+
+ @Path("wadlBeanParamFieldTest")
+ private static class TestResourceFieldBeanParam {
+
+ @QueryParam("classFieldQueryParam")
+ private String classFieldQueryParam;
+
+ @BeanParam
+ private WadlConstructorInitializedBean bean;
+
+ @BeanParam
+ private WadlSmallBean wadlSmallBean;
+
+ @POST
+ @Path("singleBean/{path}")
+ public String postBeanParam(@QueryParam("methodParam") int methodParam) {
+ return "";
+ }
+
+ }
+
+ /**
+ * The purpose of this unknown annotation is to verify that a usage of an unknown annotation in a {@link BeanParam} annotated
+ * class does not cause a failure during WADL generation.
+ */
+ @Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ @interface WadlUnknownAnnotation {
+
+ String value();
+ }
+
+ public static class WadlSmallBean {
+
+ @HeaderParam("header")
+ private String headerParam;
+
+ @PathParam("path")
+ private String pathParam;
+
+ public WadlSmallBean(WadlFullBean bean) {
+ headerParam = bean.getHeaderParam();
+ pathParam = bean.getPathParam();
+ }
+ }
+
+ public static class WadlEncodedBean {
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @Encoded
+ @QueryParam("query")
+ private String queryParam;
+
+ public WadlEncodedBean(String matrixParam, String queryParam) {
+ this.matrixParam = matrixParam;
+ this.queryParam = queryParam;
+ }
+
+ }
+
+ public static class WadlFullBean {
+
+ @HeaderParam("header")
+ private String headerParam;
+
+ @PathParam("path")
+ private String pathParam;
+
+ @MatrixParam("matrix")
+ private String matrixParam;
+
+ @QueryParam("query")
+ private String queryParam;
+
+ @CookieParam("cookie")
+ private String cookie;
+
+ @FormParam("form")
+ private String formParam;
+
+ @WadlUnknownAnnotation("unknown")
+ private String unknownAnnotationParam;
+
+ @Context
+ private Request request;
+
+ private boolean overrideRequestNull;
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public void setCookie(String cookie) {
+ this.cookie = cookie;
+ }
+
+ public String getFormParam() {
+ return formParam;
+ }
+
+ public void setFormParam(String formParam) {
+ this.formParam = formParam;
+ }
+
+ public String getHeaderParam() {
+ return headerParam;
+ }
+
+ public void setHeaderParam(String headerParam) {
+ this.headerParam = headerParam;
+ }
+
+ public String getMatrixParam() {
+ return matrixParam;
+ }
+
+ public void setMatrixParam(String matrixParam) {
+ this.matrixParam = matrixParam;
+ }
+
+ public String getPathParam() {
+ return pathParam;
+ }
+
+ public void setPathParam(String pathParam) {
+ this.pathParam = pathParam;
+ }
+
+ public String getQueryParam() {
+ return queryParam;
+ }
+
+ public void setQueryParam(String queryParam) {
+ this.queryParam = queryParam;
+ }
+
+ public Request getRequest() {
+ return request;
+ }
+
+ public void setRequest(Request request) {
+ this.request = request;
+ }
+
+ public boolean isOverrideRequestNull() {
+ return overrideRequestNull;
+ }
+
+ public void setOverrideRequestNull(boolean overrideRequestNull) {
+ this.overrideRequestNull = overrideRequestNull;
+ }
+
+ public String getUnknownAnnotationParam() {
+ return unknownAnnotationParam;
+ }
+
+ public void setUnknownAnnotationParam(String unknownAnnotationParam) {
+ this.unknownAnnotationParam = unknownAnnotationParam;
+ }
+ }
+
+ public static class WadlConstructorInitializedBean {
+
+ private String headerParam;
+ private String pathParam;
+ private String matrixParam;
+ private String queryParam;
+ private String cookie;
+ private String formParam;
+ private String unknownAnnotationParam;
+ private Request request;
+
+ public WadlConstructorInitializedBean(@CookieParam("cookie") String cookie,
+ @FormParam("form") String formParam,
+ @HeaderParam("header") String headerParam,
+ @MatrixParam("matrix") String matrixParam,
+ @QueryParam("query") String queryParam,
+ @PathParam("path") String pathParam,
+ @WadlUnknownAnnotation("unknown") String unknownAnnotationParam,
+ @Context Request request) {
+ this.cookie = cookie;
+ this.formParam = formParam;
+ this.headerParam = headerParam;
+ this.matrixParam = matrixParam;
+ this.queryParam = queryParam;
+ this.pathParam = pathParam;
+ this.unknownAnnotationParam = unknownAnnotationParam;
+ this.request = request;
+ }
+
+ private boolean overrideRequestNull;
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public void setCookie(String cookie) {
+ this.cookie = cookie;
+ }
+
+ public String getFormParam() {
+ return formParam;
+ }
+
+ public void setFormParam(String formParam) {
+ this.formParam = formParam;
+ }
+
+ public String getHeaderParam() {
+ return headerParam;
+ }
+
+ public void setHeaderParam(String headerParam) {
+ this.headerParam = headerParam;
+ }
+
+ public String getMatrixParam() {
+ return matrixParam;
+ }
+
+ public void setMatrixParam(String matrixParam) {
+ this.matrixParam = matrixParam;
+ }
+
+ public String getPathParam() {
+ return pathParam;
+ }
+
+ public void setPathParam(String pathParam) {
+ this.pathParam = pathParam;
+ }
+
+ public String getQueryParam() {
+ return queryParam;
+ }
+
+ public void setQueryParam(String queryParam) {
+ this.queryParam = queryParam;
+ }
+
+ public Request getRequest() {
+ return request;
+ }
+
+ public void setRequest(Request request) {
+ this.request = request;
+ }
+
+ public boolean isOverrideRequestNull() {
+ return overrideRequestNull;
+ }
+
+ public void setOverrideRequestNull(boolean overrideRequestNull) {
+ this.overrideRequestNull = overrideRequestNull;
+ }
+
+ public String getUnknownAnnotationParam() {
+ return unknownAnnotationParam;
+ }
+
+ public void setUnknownAnnotationParam(String unknownAnnotationParam) {
+ this.unknownAnnotationParam = unknownAnnotationParam;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlEmptyMediaTypeTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlEmptyMediaTypeTest.java
new file mode 100644
index 0000000..085c20c
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlEmptyMediaTypeTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.wadl;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests, that Jersey returns wildcard mediaType in case no response representation was specified.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class WadlEmptyMediaTypeTest extends JerseyTest {
+
+ @Path("test")
+ public static class WadlEmptyMediaTypeTestResource {
+ @Path("getEmpty")
+ @GET
+ public String getEmpty() {
+ return "No @Produces annotation";
+ }
+
+ @Path("getText")
+ @Produces("text/plain")
+ @GET
+ public String getText() {
+ return "Produces text/plain";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(WadlEmptyMediaTypeTestResource.class);
+ }
+
+ @Test
+ public void testOverride() throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
+ WebTarget target = target("/application.wadl");
+ String wadl = target.request().get(String.class);
+
+ InputSource is = new InputSource(new StringReader(wadl));
+ Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
+
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ String val = xpath.evaluate("//method[@id='getEmpty']/response/representation/@mediaType", document);
+ assertEquals("*/*", val);
+
+ val = xpath.evaluate("//method[@id='getText']/response/representation/@mediaType", document);
+ assertEquals("text/plain", val);
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
new file mode 100644
index 0000000..be2115c
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
@@ -0,0 +1,1310 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.wadl;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import javax.inject.Named;
+import javax.xml.XMLConstants;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.util.SaxHelper;
+import org.glassfish.jersey.internal.util.SimpleNamespaceResolver;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.wadl.WadlApplicationContext;
+import org.glassfish.jersey.server.wadl.WadlGenerator;
+import org.glassfish.jersey.server.wadl.config.WadlGeneratorConfig;
+import org.glassfish.jersey.server.wadl.config.WadlGeneratorDescription;
+import org.glassfish.jersey.server.wadl.internal.WadlGeneratorImpl;
+import org.glassfish.jersey.server.wadl.internal.WadlUtils;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.ElementQualifier;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableMap;
+
+import com.sun.research.ws.wadl.Method;
+import com.sun.research.ws.wadl.Param;
+import com.sun.research.ws.wadl.Request;
+import com.sun.research.ws.wadl.Resource;
+import com.sun.research.ws.wadl.Resources;
+
+/**
+ * WADL use case tests.
+ *
+ * @author Marc Hadley
+ * @author Miroslav Fuksa
+ * @author Michal Gajdos
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ WadlResourceTest.Wadl1Test.class,
+ WadlResourceTest.Wadl2Test.class,
+ WadlResourceTest.Wadl3Test.class,
+ WadlResourceTest.Wadl4Test.class,
+ WadlResourceTest.Wadl5Test.class,
+ WadlResourceTest.Wadl6Test.class,
+ WadlResourceTest.Wadl7Test.class,
+ WadlResourceTest.Wadl8Test.class,
+ WadlResourceTest.Wadl9Test.class,
+ WadlResourceTest.Wadl10Test.class,
+ WadlResourceTest.Wadl11Test.class,
+})
+public class WadlResourceTest {
+
+ /**
+ * Extracts WADL as {@link Document} from given {@link Response}.
+ *
+ * @param response The response to extract {@code Document} from.
+ * @return The extracted {@code Document}.
+ * @throws ParserConfigurationException In case of parser configuration issues.
+ * @throws SAXException In case of parsing issues.
+ * @throws IOException In case of IO error.
+ */
+ static Document extractWadlAsDocument(final Response response) throws ParserConfigurationException, SAXException,
+ IOException {
+ assertEquals(200, response.getStatus());
+ final File tmpFile = response.readEntity(File.class);
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+ final Document d = b.parse(tmpFile);
+ Wadl5Test.printSource(new DOMSource(d));
+ return d;
+ }
+
+ private static String nodeAsString(final Object resourceNode) throws TransformerException {
+ StringWriter writer = new StringWriter();
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.transform(new DOMSource((Node) resourceNode), new StreamResult(writer));
+ return writer.toString();
+ }
+
+ public static class Wadl7Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestRootResource.class);
+ }
+
+ @Path("root")
+ public static class TestRootResource {
+
+ @Path("{template}")
+ @GET
+ public String getSub() {
+ return "get";
+ }
+
+ @GET
+ public String get() {
+ return "getroot";
+ }
+ }
+
+ @Test
+ public void testPathTemplateInSubResourceMethod() throws ParserConfigurationException, SAXException, IOException,
+ XPathExpressionException {
+ final Response response = target("root/foo").request(MediaTypes.WADL_TYPE).options();
+ assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testPathTemplateInSubResourceMethod2() throws ParserConfigurationException, SAXException, IOException,
+ XPathExpressionException {
+ final Response response = target("root").request(MediaTypes.WADL_TYPE).options();
+ assertEquals(200, response.getStatus());
+ }
+ }
+
+ public static class Wadl5Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(WidgetsResource.class, ExtraResource.class);
+ }
+
+ @Path("foo")
+ public static class ExtraResource {
+
+ @GET
+ @Produces("application/xml")
+ public String getRep() {
+ return null;
+ }
+ }
+
+ @Path("widgets")
+ public static class WidgetsResource {
+
+ @GET
+ @Produces({"application/xml", "application/json"})
+ public String getWidgets() {
+ return null;
+ }
+
+ @POST
+ @Consumes({"application/xml"})
+ @Produces({"application/xml", "application/json"})
+ public String createWidget(final String bar, @MatrixParam("test") final String test) {
+ return bar;
+ }
+
+ @PUT
+ @Path("{id}")
+ @Consumes("application/xml")
+ public void updateWidget(final String bar, @PathParam("id") final int id) {
+ }
+
+ @GET
+ @Path("{id}")
+ @Produces({"application/xml", "application/json"})
+ public String getWidget(@PathParam("id") final int id) {
+ return null;
+ }
+
+ @DELETE
+ @Path("{id}")
+ public void deleteWidget(@PathParam("id") final int id) {
+ }
+
+ @Path("{id}/verbose")
+ public ExtraResource getVerbose(@PathParam("id") final int id) {
+ return new ExtraResource();
+ }
+ }
+
+ @Test
+ public void testDisableWadl() throws ExecutionException, InterruptedException {
+ final ResourceConfig rc = new ResourceConfig(WidgetsResource.class, ExtraResource.class);
+ rc.property(ServerProperties.WADL_FEATURE_DISABLE, true);
+
+ final ApplicationHandler applicationHandler = new ApplicationHandler(rc);
+
+ final ContainerResponse containerResponse = applicationHandler.apply(new ContainerRequest(
+ URI.create("/"), URI.create("/application.wadl"),
+ "GET", null, new MapPropertiesDelegate())).get();
+
+ assertEquals(404, containerResponse.getStatus());
+ }
+
+ @Test
+ public void testEnableWadl() throws ExecutionException, InterruptedException {
+ final ResourceConfig rc = new ResourceConfig(WidgetsResource.class, ExtraResource.class);
+ rc.property(ServerProperties.WADL_FEATURE_DISABLE, false);
+
+ final ApplicationHandler applicationHandler = new ApplicationHandler(rc);
+
+ final ContainerResponse containerResponse = applicationHandler.apply(new ContainerRequest(
+ URI.create("/"), URI.create("/application.wadl"),
+ "GET", null, new MapPropertiesDelegate())).get();
+
+ assertEquals(200, containerResponse.getStatus());
+ }
+
+ public static void printSource(final Source source) {
+ try {
+ System.out.println("---------------------");
+ final Transformer trans = TransformerFactory.newInstance().newTransformer();
+ final Properties oprops = new Properties();
+ oprops.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ oprops.put(OutputKeys.INDENT, "yes");
+ oprops.put(OutputKeys.METHOD, "xml");
+ trans.setOutputProperties(oprops);
+ trans.transform(source, new StreamResult(System.out));
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static String getXmlSchemaNamespacePrefix(final Node elementNode) {
+ final NamedNodeMap attributes = elementNode.getAttributes();
+
+ for (int i = 0; i < attributes.getLength(); i++) {
+ final Node item = attributes.item(i);
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(item.getNodeValue())) {
+ return item.getLocalName();
+ }
+ }
+
+ return "xs";
+ }
+
+ /**
+ * Test WADL generation.
+ *
+ * @throws Exception in case of unexpected test failure.
+ */
+ @Test
+ public void testGetWadl() throws Exception {
+ final File tmpFile = target("application.wadl").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request().get(File.class);
+
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+ final Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ // check base URI
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 4
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("6", val);
+ // check only once resource with for {id}
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only once resource with for {id}/verbose
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}/verbose'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only once resource with for widgets
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check 3 methods for {id}
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("6", val);
+ // check 2 methods for widgets
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("5", val);
+ // check 1 matrix param on resource
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:param[@name='test'])", d,
+ XPathConstants.STRING);
+ assertEquals("1", val);
+ // check type of {id} is int
+ String prefix = getXmlSchemaNamespacePrefix(
+ (Node) xp.evaluate("//wadl:resource[@path='{id}']/wadl:param[@name='id']", d, XPathConstants.NODE));
+ val = (String) xp.evaluate("//wadl:resource[@path='{id}']/wadl:param[@name='id']/@type", d, XPathConstants.STRING);
+ assertEquals(val, (prefix == null ? "" : prefix + ":") + "int");
+ // check number of output representations is two
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method[@name='GET']/wadl:response/wadl"
+ + ":representation)", d, XPathConstants.STRING);
+ assertEquals("2", val);
+ // check number of output representations is one
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method[@name='POST']/wadl:request/wadl"
+ + ":representation)", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check type of {id}/verbose is int
+ prefix = getXmlSchemaNamespacePrefix(
+ (Node) xp.evaluate("//wadl:resource[@path='{id}/verbose']/wadl:param[@name='id']", d, XPathConstants.NODE));
+ val = (String) xp.evaluate("//wadl:resource[@path='{id}/verbose']/wadl:param[@name='id']/@type", d,
+ XPathConstants.STRING);
+ assertEquals(val, (prefix == null ? "" : prefix + ":") + "int");
+ }
+
+ @Test
+ public void testLastModifiedGET() {
+ final WebTarget target = target("/application.wadl");
+
+ final Response r = target.queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true").request().get(Response.class);
+ assertTrue(r.getHeaders().containsKey("Last-modified"));
+ }
+
+ @Test
+ public void testLastModifiedOPTIONS() {
+ final WebTarget target = target("/widgets/3/verbose");
+
+ final Response r = target.queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true").request(MediaTypes.WADL_TYPE)
+ .options();
+ System.out.println(r.readEntity(String.class));
+ assertTrue(r.getHeaders().containsKey("Last-modified"));
+ }
+
+ @Test
+ public void testOptionsResourceWadl() throws ParserConfigurationException, XPathExpressionException, IOException,
+ SAXException {
+ // test WidgetsResource
+ Response response = target("/widgets").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request(MediaTypes.WADL_TYPE).options();
+ assertEquals(200, response.getStatus());
+ File tmpFile = response.readEntity(File.class);
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ DocumentBuilder b = bf.newDocumentBuilder();
+ Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ // check base URI
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 3 (no ExtraResource details included)
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("3", val);
+ // check only once resource with for {id}
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only once resource with for {id}/verbose
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}/verbose'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only once resource with for widgets
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check 3 methods for {id}
+ val = (String) xp.evaluate("count(//wadl:resource[@path='{id}']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("6", val);
+ // check 2 methods for widgets
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("5", val);
+ // check type of {id} is int
+ final String prefix = getXmlSchemaNamespacePrefix(
+ (Node) xp.evaluate("//wadl:resource[@path='{id}']/wadl:param[@name='id']", d, XPathConstants.NODE));
+ val = (String) xp.evaluate("//wadl:resource[@path='{id}']/wadl:param[@name='id']/@type", d, XPathConstants.STRING);
+ assertEquals(val, (prefix == null ? "" : prefix + ":") + "int");
+ // check number of output representations is two
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method[@name='GET']/wadl:response/wadl"
+ + ":representation)", d, XPathConstants.STRING);
+ assertEquals("2", val);
+ // check number of output representations is one
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets']/wadl:method[@name='POST']/wadl:request/wadl"
+ + ":representation)", d, XPathConstants.STRING);
+ assertEquals("1", val);
+
+ response = target("/foo").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request(MediaTypes.WADL_TYPE).options();
+ assertEquals(200, response.getStatus());
+ tmpFile = response.readEntity(File.class);
+ b = bf.newDocumentBuilder();
+ d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ // check base URI
+ val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 1 (no ExtraResource details included)
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only once resource with path foo
+ val = (String) xp.evaluate("count(//wadl:resource[@path='foo'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check 1 methods for foo
+ val = (String) xp.evaluate("count(//wadl:resource[@path='foo']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("4", val);
+ }
+
+ @Test
+ public void testOptionsLocatorWadl() throws ParserConfigurationException, SAXException, IOException,
+ XPathExpressionException {
+
+ // test WidgetsResource
+ final File tmpFile = target("/widgets/3/verbose").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request(MediaTypes.WADL_TYPE).options(File.class);
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+ final Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ // check base URI
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 1 (no ExtraResource details included)
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals(val, "1");
+ // check only once resource with path
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets/3/verbose'])", d, XPathConstants.STRING);
+ assertEquals(val, "1");
+ // check 1 methods
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets/3/verbose']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("4", val);
+ }
+
+ @Test
+ public void testOptionsSubResourceWadl() throws ParserConfigurationException, SAXException, IOException,
+ XPathExpressionException {
+ // test WidgetsResource
+ final File tmpFile = target("/widgets/3").queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true")
+ .request(MediaTypes.WADL_TYPE).options(File.class);
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+ final Document d = b.parse(tmpFile);
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check total number of resources is 1
+ val = (String) xp.evaluate("count(//wadl:resource)", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check only one resource with for {id}
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets/3'])", d, XPathConstants.STRING);
+ assertEquals("1", val);
+ // check 3 methods
+ val = (String) xp.evaluate("count(//wadl:resource[@path='widgets/3']/wadl:method)", d, XPathConstants.STRING);
+ assertEquals("6", val);
+ }
+
+ public static class MyWadlGeneratorConfig extends WadlGeneratorConfig {
+
+ @Override
+ public List<WadlGeneratorDescription> configure() {
+ return generator(MyWadlGenerator.class).descriptions();
+ }
+
+ public static class MyWadlGenerator extends WadlGeneratorImpl {
+
+ public static final String CUSTOM_RESOURCES_BASE_URI = "http://myBaseUri";
+
+ @Override
+ public Resources createResources() {
+ final Resources resources = super.createResources();
+ resources.setBase(CUSTOM_RESOURCES_BASE_URI);
+
+ return resources;
+ }
+
+ @Override
+ public void setWadlGeneratorDelegate(final WadlGenerator delegate) {
+ // nothing
+ }
+ }
+ }
+
+ /**
+ * Test overriding WADL's /application/resources/@base attribute.
+ *
+ * @throws Exception in case of unexpected test failure.
+ */
+ @Test
+ public void testCustomWadlResourcesBaseUri() throws Exception {
+ final ResourceConfig rc = new ResourceConfig(WidgetsResource.class, ExtraResource.class);
+ rc.property(ServerProperties.WADL_GENERATOR_CONFIG, MyWadlGeneratorConfig.class.getName());
+
+ final ApplicationHandler applicationHandler = new ApplicationHandler(rc);
+
+ final ContainerResponse containerResponse = applicationHandler.apply(new ContainerRequest(
+ URI.create("/"), URI.create("/application.wadl"),
+ "GET", null, new MapPropertiesDelegate())).get();
+
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+
+ ((ByteArrayInputStream) containerResponse.getEntity()).reset();
+
+ final Document d = b.parse((InputStream) containerResponse.getEntity());
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ // check base URI
+ final String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, MyWadlGeneratorConfig.MyWadlGenerator.CUSTOM_RESOURCES_BASE_URI);
+ }
+
+ @Path("emptyproduces")
+ public static class EmptyProducesTestResource {
+
+ @PUT
+ @Produces({})
+ public Response put(final String str) {
+ return Response.ok().build();
+ }
+
+ @POST
+ @Path("/sub")
+ @Produces({})
+ public Response post(final String str) {
+ return Response.ok().build();
+ }
+ }
+
+ @Test
+ public void testEmptyProduces() throws Exception {
+ final ResourceConfig rc = new ResourceConfig(EmptyProducesTestResource.class);
+ rc.property(ServerProperties.WADL_FEATURE_DISABLE, false);
+
+ final ApplicationHandler applicationHandler = new ApplicationHandler(rc);
+
+ final ContainerResponse containerResponse = applicationHandler.apply(new ContainerRequest(
+ URI.create("/"), URI.create("/application.wadl"),
+ "GET", null, new MapPropertiesDelegate())).get();
+
+ assertEquals(200, containerResponse.getStatus());
+
+ ((ByteArrayInputStream) containerResponse.getEntity()).reset();
+
+ final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+ bf.setNamespaceAware(true);
+ bf.setValidating(false);
+ if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+ bf.setXIncludeAware(false);
+ }
+ final DocumentBuilder b = bf.newDocumentBuilder();
+ final Document d = b.parse((InputStream) containerResponse.getEntity());
+ printSource(new DOMSource(d));
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ final NodeList responseElements = (NodeList) xp.evaluate(
+ "/wadl:application/wadl:resources[@path!='application.wadl']//wadl:method/wadl:response", d,
+ XPathConstants.NODESET);
+
+ for (int i = 0; i < responseElements.getLength(); i++) {
+ final Node item = responseElements.item(i);
+
+ assertEquals(0, item.getChildNodes().getLength());
+ assertEquals(0, item.getAttributes().getLength());
+ }
+ }
+ }
+
+ public static class Wadl1Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RootResource.class);
+ }
+
+ @Path("root")
+ public static class RootResource {
+
+ @Path("loc")
+ public Object getSub() {
+ return new SubResource();
+ }
+
+ @Path("switch")
+ @POST
+ public void switchMethod(@Context final WadlApplicationContext wadlApplicationContext) {
+ wadlApplicationContext.setWadlGenerationEnabled(!wadlApplicationContext.isWadlGenerationEnabled());
+
+ }
+ }
+
+ public static class SubResource {
+
+ @Path("loc")
+ public Object getSub() {
+ return new SubResource();
+ }
+
+ @GET
+ @Produces("text/plain")
+ public String hello() {
+ return "Hello World !";
+ }
+
+ @GET
+ @Path("sub")
+ @Produces("text/plain")
+ public String helloSub() {
+ return "Hello World !";
+ }
+ }
+
+ @Test
+ public void testRecursive() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ _testRecursiveWadl("root/loc");
+ }
+
+ @Test
+ public void mytest() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ final Response response = target().path("root/test").request().get();
+ System.out.println(response.readEntity(String.class));
+ }
+
+ @Test
+ public void testRecursive2() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ _testRecursiveWadl("root/loc/loc");
+ }
+
+ private void _testRecursiveWadl(final String path) throws ParserConfigurationException, SAXException, IOException,
+ XPathExpressionException {
+ final Document d = extractWadlAsDocument(target(path).request(MediaTypes.WADL_TYPE).options());
+
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+
+ // check only one resource with for 'root/loc'
+ val = (String) xp.evaluate("count(//wadl:resource[@path='" + path + "'])", d, XPathConstants.STRING);
+ assertEquals(val, "1");
+ }
+
+ }
+
+ public static class Wadl2Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RootResource1.class, RootResource2.class);
+ }
+
+ @Path("root1")
+ public static class RootResource1 {
+
+ @Path("loc")
+ public Wadl1Test.SubResource getSub() {
+ return new Wadl1Test.SubResource();
+ }
+ }
+
+ @Path("root2")
+ public static class RootResource2 {
+
+ @Path("loc")
+ public Wadl1Test.SubResource getSub() {
+ return new Wadl1Test.SubResource();
+ }
+ }
+
+ @Test
+ public void testRecursive2() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ final Document d = extractWadlAsDocument(target("/application.wadl")
+ .queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true").request().get());
+
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+ String val = (String) xp.evaluate("/wadl:application/wadl:resources/@base", d, XPathConstants.STRING);
+ assertEquals(val, getBaseUri().toString());
+ // check only one resource with for 'root/loc'
+ val = (String) xp.evaluate("count(//wadl:resource[@path='loc'])", d, XPathConstants.STRING);
+ assertEquals("4", val);
+ // check for method with id of hello
+ val = (String) xp.evaluate("count(//wadl:resource[@path='loc']/wadl:method[@id='hello'])", d, XPathConstants.STRING);
+ assertEquals("2", val);
+ }
+ }
+
+ public static class Wadl3Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FormResource.class);
+ }
+
+ @Path("form")
+ public static class FormResource {
+
+ @POST
+ @Consumes("application/x-www-form-urlencoded")
+ public void post(
+ @FormParam("a") final String a,
+ @FormParam("b") final String b,
+ @FormParam("c") final JaxbBean c,
+ @FormParam("c") final FormDataContentDisposition cdc,
+ final Form form) {
+ }
+
+ }
+
+ @Test
+ public void testFormParam() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ final Document d = extractWadlAsDocument(target("/application.wadl").request().get());
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ final String requestPath = "//wadl:resource[@path='form']/wadl:method[@name='POST']/wadl:request";
+ final String representationPath = requestPath + "/wadl:representation";
+
+ // check number of request params is zero
+ int count = ((Double) xp.evaluate("count(" + requestPath + "/wadl:param)", d, XPathConstants.NUMBER)).intValue();
+ assertEquals(0, count);
+
+ // check number of request representations is one
+ count = ((Double) xp.evaluate("count(" + representationPath + ")", d, XPathConstants.NUMBER)).intValue();
+ assertEquals(1, count);
+
+ // check number of request representation params is three
+ count = ((Double) xp.evaluate("count(" + representationPath + "/wadl:param)", d, XPathConstants.NUMBER)).intValue();
+ assertEquals(3, count);
+
+ // check the style of the request representation param is 'query'
+ String val = (String) xp.evaluate(representationPath + "/wadl:param[@name='a']/@style", d, XPathConstants.STRING);
+ assertEquals("query", val);
+ val = (String) xp.evaluate(representationPath + "/wadl:param[@name='b']/@style", d, XPathConstants.STRING);
+ assertEquals("query", val);
+
+ }
+ }
+
+ public static class Wadl4Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FieldParamResource.class);
+ }
+
+ @Path("fieldParam/{pp}")
+ public static class FieldParamResource {
+
+ @HeaderParam("hp")
+ String hp;
+ @MatrixParam("mp")
+ String mp;
+ @PathParam("pp")
+ String pp;
+
+ private String q;
+
+ @QueryParam("q")
+ public void setQ(final String q) {
+ this.q = q;
+ }
+
+ // these should not be included in WADL
+ @Context
+ UriInfo uriInfo;
+ @Named("fakeParam")
+ String fakeParam;
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return pp;
+ }
+
+ }
+
+ @Test
+ public void testFieldParam() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+ final String path = "fieldParam";
+ _testFieldAndSetterParam(target("/application.wadl").request().get(), path);
+ }
+
+ private static void _testFieldAndSetterParam(final Response response, final String path)
+ throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
+
+ final Document d = extractWadlAsDocument(response);
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ final String resourcePath = String.format("//wadl:resource[@path='%s/{pp}']", path);
+ final String methodPath = resourcePath + "/wadl:method[@name='GET']";
+
+ // check number of resource methods is one
+ final int methodCount = ((Double) xp.evaluate("count(" + methodPath + ")", d, XPathConstants.NUMBER)).intValue();
+ assertThat("Unexpected number of methods on path '" + methodPath + "'", methodCount, equalTo(1));
+
+ final Map<String, String> paramStyles = new HashMap<>();
+ paramStyles.put("mp", "matrix");
+ paramStyles.put("pp", "template");
+
+ // check the number of resource params
+ final String resourceParamsCountXPath = String.format("count(%s/wadl:param)", resourcePath);
+ final int resourceParamsCount = ((Double) xp.evaluate(resourceParamsCountXPath, d, XPathConstants.NUMBER)).intValue();
+ assertThat("Number of resource parameters does not match.", resourceParamsCount, equalTo(2));
+
+ for (final Map.Entry<String, String> param : paramStyles.entrySet()) {
+
+ final String pName = param.getKey();
+ final String pStyle = param.getValue();
+
+ final String paramXPath = String.format("%s/wadl:param[@name='%s']", resourcePath, pName);
+
+ // check number of params is one
+ final int pc = ((Double) xp.evaluate("count(" + paramXPath + ")", d, XPathConstants.NUMBER)).intValue();
+ assertThat("Number of " + pStyle + " parameters '" + pName + "' does not match.", pc, equalTo(1));
+
+ // check the style of the param
+ final String style = (String) xp.evaluate(paramXPath + "/@style", d, XPathConstants.STRING);
+ assertThat("Parameter '" + pName + "' style does not match.", pStyle, equalTo(style));
+ }
+
+ paramStyles.clear();
+ paramStyles.put("hp", "header");
+ paramStyles.put("q", "query");
+
+ // check the number of request params
+ final String requestParamsCountXPath = String.format("count(%s/wadl:request/wadl:param)", methodPath);
+ final int requestParamsCount = ((Double) xp.evaluate(requestParamsCountXPath, d, XPathConstants.NUMBER)).intValue();
+ assertThat("Number of request parameters does not match.", requestParamsCount, equalTo(2));
+
+ for (final Map.Entry<String, String> param : paramStyles.entrySet()) {
+
+ final String pName = param.getKey();
+ final String pStyle = param.getValue();
+
+ final String paramXPath = String.format("%s/wadl:request/wadl:param[@name='%s']", methodPath, pName);
+
+ // check that the number of params is one
+ final int pc = ((Double) xp.evaluate("count(" + paramXPath + ")", d, XPathConstants.NUMBER)).intValue();
+ assertThat("Number of " + pStyle + " parameters '" + pName + "' does not match.", pc, equalTo(1));
+
+ // check the style of the param
+ final String style = (String) xp.evaluate(paramXPath + "/@style", d, XPathConstants.STRING);
+ assertThat("Parameter '" + pName + "' style does not match.", pStyle, equalTo(style));
+ }
+ }
+ }
+
+ /**
+ * Tests OPTIONS method on a resource method annotated with @Path and containing a leading '/'.
+ */
+ public static class Wadl6Test extends JerseyTest {
+
+ @Path("wadl6test")
+ public static class Resource {
+
+ @GET
+ @Path("foo1")
+ public String foo1() {
+ return "foo1";
+ }
+
+ @GET
+ @Path("/foo2")
+ public String foo2() {
+ return "foo2";
+ }
+
+ @GET
+ @Path("foo3/")
+ public String foo3() {
+ return "foo3";
+ }
+
+ @GET
+ @Path("/foo4/")
+ public String foo4() {
+ return "foo4";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testGetWithPathAndLeadingSlash() throws Exception {
+ for (int i = 1; i < 5; i++) {
+ final String[] paths = {
+ "foo" + i,
+ "/foo" + i,
+ "foo" + i + '/',
+ "/foo" + i + '/'
+ };
+
+ for (final String path : paths) {
+ final Response response = target("wadl6test")
+ .path(path)
+ .request("application/vnd.sun.wadl+xml")
+ .options();
+ assertEquals(200, response.getStatus());
+ final String document = response.readEntity(String.class);
+
+ // check that the resulting document contains a method element with id="fooX"
+ assertTrue(document.replaceAll("\n", " ").matches(".*<method[^>]+id=\"foo" + i + "\"[^>]*>.*"));
+ }
+ }
+ }
+ }
+
+ public static class Wadl8Test extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResourceA.class, ResourceB.class, ResourceSpecific.class);
+ }
+
+ @Path("{a}")
+ public static class ResourceA {
+
+ @GET
+ public String getA() {
+ return "a";
+ }
+ }
+
+ @Path("{b}")
+ public static class ResourceB {
+
+ @POST
+ public String postB(final String str) {
+ return "b";
+ }
+ }
+
+ @Path("resource")
+ public static class ResourceSpecific {
+
+ @GET
+ @Path("{templateA}")
+ public String getTemplateA() {
+ return "template-a";
+ }
+
+ @POST
+ @Path("{templateB}")
+ public String postTemplateB(final String str) {
+ return "template-b";
+ }
+ }
+
+ @Test
+ @Ignore("JERSEY-1670: WADL Options invoked on resources with same template returns only methods from one of them.")
+ // TODO: fix
+ public void testWadlForAmbiguousResourceTemplates()
+ throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
+ final Response response = target().path("foo").request(MediaTypes.WADL_TYPE).options();
+ final Document d = extractWadlAsDocument(response);
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ String result = (String) xp.evaluate("//wadl:resource/wadl:method[@name='GET']/@id", d, XPathConstants.STRING);
+ assertEquals("getA", result);
+
+ result = (String) xp.evaluate("//wadl:resource/wadl:method[@name='POST']/@id", d, XPathConstants.STRING);
+ assertEquals("postB", result);
+ }
+
+ @Test
+ @Ignore("JERSEY-1670: WADL Options invoked on resources with same template returns only methods from one of them.")
+ // TODO: fix
+ public void testWadlForAmbiguousChildResourceTemplates()
+ throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
+ final Response response = target().path("resource/bar").request(MediaTypes.WADL_TYPE).options();
+
+ final Document d = extractWadlAsDocument(response);
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+
+ String result = (String) xp.evaluate("//wadl:resource/wadl:method[@name='GET']/@id", d, XPathConstants.STRING);
+ assertEquals("getTemplateA", result);
+
+ result = (String) xp.evaluate("//wadl:resource/wadl:method[@name='POST']/@id", d, XPathConstants.STRING);
+ assertEquals("postTemplateB", result);
+ }
+ }
+
+ /**
+ * Tests usage of property {@link ServerProperties#METAINF_SERVICES_LOOKUP_DISABLE}. Wadl is registered automatically every
+ * time and can be turned off only via {@link ServerProperties#WADL_FEATURE_DISABLE}.
+ */
+ public static class Wadl9Test extends JerseyTest {
+
+ @Path("wadl9test")
+ public static class Resource {
+
+ @GET
+ public String foo() {
+ return "foo";
+ }
+
+ } // class Resource
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(Resource.class);
+ resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
+
+ return resourceConfig;
+ }
+
+ @Test
+ public void testWadl() throws Exception {
+ final Response response = target("/application.wadl").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.hasEntity(), is(true));
+ }
+
+ } // class Wadl9Test
+
+ /**
+ * Tests whether boolean getters have been generated with "is" prefix.
+ */
+ public static class Wadl10Test extends JerseyTest {
+
+ @Path("wadl10test")
+ public static class Resource {
+
+ @GET
+ public Boolean foo(@QueryParam("q") final Boolean q) {
+ return q;
+ }
+
+ } // class Resource
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testWadl() throws Exception {
+ final Response response = target("/application.wadl").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.hasEntity(), is(true));
+
+ final Method method = (Method) response.readEntity(com.sun.research.ws.wadl.Application.class) // wadl
+ .getResources().get(0).getResource().get(0) // resource
+ .getMethodOrResource().get(0); // method
+ final Param param = method.getRequest().getParam().get(0); // param
+
+ // not interested in returned value, only whether we can compile.
+ assertThat(param.isRequired(), notNullValue());
+ assertThat(param.isRepeating(), notNullValue());
+ }
+
+ } // class Wadl10Test
+
+ /**
+ * Tests whether unknown annotation affects a WADL correctness.
+ */
+ public static class Wadl11Test extends JerseyTest {
+
+ @Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.TYPE})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Inherited
+ public @interface UnknownAnnotation {
+ }
+
+ @Path("annotated")
+ @Consumes("application/json")
+ @UnknownAnnotation
+ public static class Annotated {
+
+ @Path("subresource")
+ @POST
+ @Produces("application/json")
+ @UnknownAnnotation
+ public Entity myMethod1(@UnknownAnnotation final Entity entity) {
+ return entity;
+ }
+
+ @Path("subresource")
+ @POST
+ @Produces("application/xml")
+ public Entity myMethod2(@UnknownAnnotation final Entity entity) {
+ return entity;
+ }
+
+ }
+
+ @Path("not-annotated")
+ @Consumes("application/json")
+ public static class Plain {
+
+ @Path("subresource")
+ @POST
+ @Produces("application/json")
+ public Entity myMethod1(final Entity entity) {
+ return entity;
+ }
+
+ @Path("subresource")
+ @POST
+ @Produces("application/xml")
+ public Entity myMethod2(final Entity entity) {
+ return entity;
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Annotated.class, Plain.class);
+ }
+
+ @Test
+ public void testWadlIsComplete() throws Exception {
+ final Response response = target("/application.wadl").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.hasEntity(), is(true));
+
+ final com.sun.research.ws.wadl.Application application =
+ response.readEntity(com.sun.research.ws.wadl.Application.class);
+
+ // "annotated/subresource"
+ final Resource resource =
+ (Resource) application.getResources().get(0).getResource().get(0).getMethodOrResource().get(0);
+
+ assertThatMethodContainsRR(resource, "myMethod1", 0);
+ assertThatMethodContainsRR(resource, "myMethod2", 1);
+
+ }
+
+ private static void assertThatMethodContainsRR(final Resource resource, final String methodName, final int methodIndex) {
+ final Method method = (Method) resource.getMethodOrResource().get(methodIndex);
+
+ assertThat(method.getId(), equalTo(methodName));
+
+ final Request request = method.getRequest();
+ final List<com.sun.research.ws.wadl.Response> response = method.getResponse();
+
+ assertThat(request, notNullValue());
+ assertThat(response.isEmpty(), is(false));
+ }
+
+ @Test
+ public void testWadlIsSameForAnnotatedAndNot() throws Exception {
+
+ final Response response = target("/application.wadl").request().get();
+
+ final Document document = extractWadlAsDocument(response);
+
+ final XPath xp = XPathFactory.newInstance().newXPath();
+ final SimpleNamespaceResolver nsContext = new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02");
+ xp.setNamespaceContext(nsContext);
+
+ final Diff diff = XMLUnit.compareXML(
+ nodeAsString(
+ xp.evaluate("//wadl:resource[@path='annotated']/wadl:resource", document,
+ XPathConstants.NODE)),
+ nodeAsString(
+ xp.evaluate("//wadl:resource[@path='not-annotated']/wadl:resource", document,
+ XPathConstants.NODE))
+ );
+ XMLUnit.setXpathNamespaceContext(
+ new SimpleNamespaceContext(ImmutableMap.of("wadl", "http://wadl.dev.java.net/2009/02")));
+ final ElementQualifier elementQualifier = new RecursiveElementNameAndTextQualifier();
+ diff.overrideElementQualifier(elementQualifier);
+ XMLAssert.assertXMLEqual(diff, true);
+
+ }
+
+ } // class Wadl11Test
+
+
+ @XmlRootElement(name = "jaxbBean")
+ public class JaxbBean {
+
+ public String value;
+
+ public JaxbBean() {
+ }
+
+ public JaxbBean(String str) {
+ value = str;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof JaxbBean)) {
+ return false;
+ }
+ return ((JaxbBean) o).value.equals(value);
+ }
+
+ public String toString() {
+ return "JAXBClass: " + value;
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/resources/CustomViewableContext/index.testp b/tests/e2e-server/src/test/resources/CustomViewableContext/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/CustomViewableContext/index.testp
diff --git a/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyReader b/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyReader
new file mode 100644
index 0000000..681227c
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyReader
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.e2e.server.AbstractDisableMetainfServicesLookupTest$UselessMessageProvider
\ No newline at end of file
diff --git a/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter b/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter
new file mode 100644
index 0000000..681227c
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.e2e.server.AbstractDisableMetainfServicesLookupTest$UselessMessageProvider
\ No newline at end of file
diff --git a/tests/e2e-server/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable b/tests/e2e-server/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
new file mode 100644
index 0000000..dcdd754
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.e2e.server.monitoring.ApplicationInfoTest$ForcedAutoDiscoverableImpl
diff --git a/tests/e2e-server/src/test/resources/ValidationMessages.properties b/tests/e2e-server/src/test/resources/ValidationMessages.properties
new file mode 100644
index 0000000..1d440e9
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/ValidationMessages.properties
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+org.glassfish.jersey.tests.e2e.server.validation.NonEmptyNames.message=at least one of the names is empty
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest/ErrorTemplateResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest/ErrorTemplateResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/BeanValidationErrorTemplateTest/ErrorTemplateResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/CustomResolvingClass/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/absolute.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateResource/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/absolute.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/absolute.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/absolute.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ErrorTemplateTest/ErrorTemplateSubResource/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/404.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/404.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/404.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/WebAppExceptionMapper/406.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/WebAppExceptionMapper/406.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExceptionViewProcessorTest/WebAppExceptionMapper/406.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.def b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitNoProducesTemplate/index.def
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/absolute.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/absolute.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/absolute.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/relative.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/relative.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTemplateProducesClass/relative.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.def b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitTwoGetProducesTemplate/index.def
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.def b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitProduceTemplateTest/ExplicitWildcardProducesTemplate/index.def
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/CustomResolvingClass/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.abc b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.abc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.abc
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/absolute.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplate/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/absolute.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/absolute.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/absolute.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/relative.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/relative.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ExplicitTemplateTest/ExplicitTemplateSubResource/relative.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplate.override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplate.override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplate.override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.inherit.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.inherit.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.inherit.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ExplicitTemplateBase.show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplate.override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplate.override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplate.override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.inherit.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.inherit.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatInheritedViewProcessorTest.ImplicitTemplateBase.inherit.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ExplicitTemplate.show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ExplicitTemplate.show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ExplicitTemplate.show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitExplicitTemplate.show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitTemplate.index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitTemplate.index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitTemplate.index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithGetTemplate.index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithGetTemplate.index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithGetTemplate.index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithSubResourceGetTemplate.sub.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithSubResourceGetTemplate.sub.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/FlatViewProcessorTest.ImplicitWithSubResourceGetTemplate.sub.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithGetTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitProducesViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest/Handler/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest/Handler/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateProgrammaticTest/Handler/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/get.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/get.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/get.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/AnotherImplicitGetResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/get.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/get.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/get.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSingletonResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSingletonResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSingletonResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSubSubResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSubSubResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitTemplateTest/ImplicitSubSubResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest/ImplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest/ImplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ImplicitViewWithResourceFilterTest/ImplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplate/override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplate/override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplate/override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/inherit.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/inherit.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/inherit.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ExplicitTemplateBase/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplate/override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplate/override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplate/override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/inherit.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/inherit.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/inherit.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/override.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/override.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/InheritedViewProcessorTest/ImplicitTemplateBase/override.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/FreemarkerResource.ftl b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/FreemarkerResource.ftl
new file mode 100644
index 0000000..c38689f
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/FreemarkerResource.ftl
@@ -0,0 +1 @@
+Model:${user}
\ No newline at end of file
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/MustacheResource.mustache b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/MustacheResource.mustache
new file mode 100644
index 0000000..e0d8fbf
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/MvcEncodingTest/MustacheResource.mustache
@@ -0,0 +1 @@
+Model:{{user}}
\ No newline at end of file
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ResolvingClassViewProcessorTest/ResolvingClass/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ResolvingClassViewProcessorTest/ResolvingClass/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ResolvingClassViewProcessorTest/ResolvingClass/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/getAsHTML b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/getAsHTML
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/getAsHTML
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/AsViewableResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/getAsHTML b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/getAsHTML
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/getAsHTML
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResource/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/getAsHTML b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/getAsHTML
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/getAsHTML
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateMethodSelectionTest/TemplateAnnotatedResourceMethod/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/absolute/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/absolute/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/absolute/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithGetTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithGetTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithGetTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/TemplateProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/absolute/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/show.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/show.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitExplicitTemplate/show.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithGetTemplate/index.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithGetTemplate/index.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithGetTemplate/index.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/ViewProcessorTest/ImplicitWithSubResourceGetTemplate/sub.testp
diff --git a/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest/Resource/index.fct b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest/Resource/index.fct
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/e2e-server/src/test/resources/org/glassfish/jersey/tests/e2e/server/mvc/spi/AbstractTemplateProcessorTest/Resource/index.fct
diff --git a/tests/e2e-testng/pom.xml b/tests/e2e-testng/pom.xml
new file mode 100644
index 0000000..4aa82b5
--- /dev/null
+++ b/tests/e2e-testng/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-testng</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-testng</name>
+
+ <description>Jersey E2E (TestNG) tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-testng</artifactId>
+ <version>2.17</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/AbstractParallelTest.java b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/AbstractParallelTest.java
new file mode 100644
index 0000000..64cd925
--- /dev/null
+++ b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/AbstractParallelTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTestNg;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Base for TestNG parallel tests. Contains one singleton resource with GET method returning incremental sequence of integers.
+ * Extensions has to implement {@link #testValue(Integer)}.
+ *
+ * @author Michal Gajdos
+ */
+@Test(threadPoolSize = 5, invocationCount = 13)
+public abstract class AbstractParallelTest extends JerseyTestNg {
+
+ @Path("/")
+ @Singleton
+ @Produces("text/plain")
+ public static class Resource {
+
+ private AtomicInteger ai = new AtomicInteger(0);
+
+ @GET
+ public int get() {
+ return ai.getAndIncrement();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ // Find first available port.
+ forceSet(TestProperties.CONTAINER_PORT, "0");
+
+ return new ResourceConfig(Resource.class);
+ }
+
+ public void test1() throws Exception {
+ test();
+ }
+
+ public void test2() throws Exception {
+ test();
+ }
+
+ public void test3() throws Exception {
+ test();
+ }
+
+ private void test() {
+ final Response response = target().request().get();
+
+ assertEquals(response.getStatus(), 200);
+ testValue(response.readEntity(Integer.class));
+ }
+
+ protected abstract void testValue(final Integer actual);
+}
diff --git a/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeClassParallelTest.java b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeClassParallelTest.java
new file mode 100644
index 0000000..8ba02b6
--- /dev/null
+++ b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeClassParallelTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.glassfish.jersey.test.ContainerPerClassTestNgStrategy;
+import org.glassfish.jersey.test.spi.TestNgStrategy;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Runs a set of tests (in parallel) against single test container instance.
+ *
+ * @author Michal Gajdos
+ */
+public class BeforeClassParallelTest extends AbstractParallelTest {
+
+ private ConcurrentMap<Integer, String> values = new ConcurrentHashMap<>();
+
+ @BeforeClass
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @AfterClass
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected TestNgStrategy configureStrategy() {
+ return new ContainerPerClassTestNgStrategy();
+ }
+
+ @Override
+ protected void testValue(final Integer actual) {
+ final String name = values.putIfAbsent(actual, Thread.currentThread().getName());
+
+ assertThat(String.format("Value %d has already been returned by client in thread %s.", actual, name),
+ name, nullValue());
+ }
+}
diff --git a/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeMethodParallelTest.java b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeMethodParallelTest.java
new file mode 100644
index 0000000..650d2d4
--- /dev/null
+++ b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/BeforeMethodParallelTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import org.glassfish.jersey.test.ContainerPerMethodTestNgStrategy;
+import org.glassfish.jersey.test.spi.TestNgStrategy;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Runs a set of tests (in parallel) each against separate test container instance.
+ *
+ * @author Michal Gajdos
+ */
+public class BeforeMethodParallelTest extends AbstractParallelTest {
+
+ @BeforeMethod
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @AfterMethod
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected TestNgStrategy configureStrategy() {
+ return new ContainerPerMethodTestNgStrategy();
+ }
+
+ @Override
+ protected void testValue(final Integer actual) {
+ assertThat(actual, is(0));
+ }
+}
diff --git a/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerClassTest.java b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerClassTest.java
new file mode 100644
index 0000000..7cf2eb7
--- /dev/null
+++ b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerClassTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTestNg;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests that container is created only once per class and each test method sends request to the same container.
+ *
+ * @author Michal Gajdos
+ */
+public class ContainerPerClassTest extends JerseyTestNg.ContainerPerClassTest {
+
+ @Path("/")
+ @Singleton
+ @Produces("text/plain")
+ public static class Resource {
+
+ private int i = 1;
+
+ @GET
+ public int get() {
+ return i++;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test(priority = 1)
+ public void first() throws Exception {
+ test(1);
+ }
+
+ @Test(priority = 2)
+ public void second() throws Exception {
+ test(2);
+ }
+
+ @Test(priority = 3)
+ public void third() throws Exception {
+ test(3);
+ }
+
+ private void test(final Integer expected) {
+ final Response response = target().request().get();
+
+ assertEquals(response.getStatus(), 200);
+ assertEquals(response.readEntity(Integer.class), expected);
+ }
+}
diff --git a/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerMethodTest.java b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerMethodTest.java
new file mode 100644
index 0000000..9b2948e
--- /dev/null
+++ b/tests/e2e-testng/src/test/java/org/glassfish/jersey/tests/e2e/ContainerPerMethodTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTestNg;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests that new container is created for each test method.
+ *
+ * @author Michal Gajdos
+ */
+public class ContainerPerMethodTest extends JerseyTestNg.ContainerPerMethodTest {
+
+ @Path("/")
+ @Singleton
+ @Produces("text/plain")
+ public static class Resource {
+
+ private int i = 1;
+
+ @GET
+ public int get() {
+ return i++;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test(priority = 1)
+ public void first() throws Exception {
+ test(1);
+ }
+
+ @Test(priority = 2)
+ public void second() throws Exception {
+ test(1);
+ }
+
+ @Test(priority = 3)
+ public void third() throws Exception {
+ test(1);
+ }
+
+ private void test(final Integer expected) {
+ final Response response = target().request().get();
+
+ assertEquals(response.getStatus(), 200);
+ assertEquals(response.readEntity(Integer.class), expected);
+ }
+}
diff --git a/tests/e2e/README b/tests/e2e/README
new file mode 100644
index 0000000..2c2456a
--- /dev/null
+++ b/tests/e2e/README
@@ -0,0 +1,20 @@
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+End-to-end tests module
+=======================
\ No newline at end of file
diff --git a/tests/e2e/pom.xml b/tests/e2e/pom.xml
new file mode 100644
index 0000000..6d9346a
--- /dev/null
+++ b/tests/e2e/pom.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e</name>
+
+ <description>Jersey E2E tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-freemarker</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-mustache</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson1</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jettison</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jdk-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth2-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>xdk</id>
+ <properties>
+ <!-- do not use security manager for xdk -->
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AbortingFilterTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AbortingFilterTest.java
new file mode 100644
index 0000000..f91c24e
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AbortingFilterTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JERSEY-2345 Reproducer.
+ * <p/>
+ * If an invalid WWW-Authenticate header is sent from the server and HttpUrlConnector is used,
+ * during processing in the Connector an Exception is thrown (HttpUrlConnection creates an instance of AuthenticateHeader class
+ * which tries to parse the header value during construction. If a scheme is missing (header value is one word),
+ * the constructor throws an exception.
+ * <p/>
+ * This cannot be "fixed" in Jersey.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class AbortingFilterTest extends JerseyTest {
+ private static Logger logger = Logger.getLogger(AbortingFilterTest.class.getName());
+
+ @Path("simple")
+ public static class SimpleTestResource {
+ @GET
+ public Response simpleTest() {
+ return Response.ok().build();
+ }
+
+ @Path("response")
+ @GET
+ public Response simpleResponseTest() {
+ return Response.ok().build();
+ }
+
+ @Path("direct")
+ @GET
+ public Response directResponseTest() {
+ return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate",
+ "oauth_problem=token_rejected").build();
+ }
+ }
+
+ public static class AbortingFilter implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ final Response.ResponseBuilder builder = Response.status(Response.Status.UNAUTHORIZED);
+ builder.header("WWW-Authenticate", "oauth_problem=token_rejected");
+ requestContext.abortWith(builder.build());
+ }
+ }
+
+ public static class AbortingResponseFilter implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ final Response.ResponseBuilder builder = Response.status(Response.Status.UNAUTHORIZED);
+ builder.header("WWW-Authenticate", "oauth_problem=token_rejected");
+ requestContext.abortWith(builder.build());
+
+ }
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(FilterDynamicBinding.class, SimpleTestResource.class, LoggingFeature.class);
+ }
+
+ /**
+ * Try to abort response in the container response filter. However, it's too late and produces an error.
+ */
+ @Test
+ public void testAbortingResponseFilter() {
+ final Response response = target().path("simple/response").request().get();
+ int status = response.getStatus();
+ logger.info("Response status is: " + status);
+ assertEquals(status, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ }
+
+ /**
+ * Try to abort response in a container request filter. With an invalid WWW-Authenticate header (according to HTTP specs)
+ * and HttpUrlConnector, it throws an exception. This is an original scenario reported by jrh3k5 on java.net
+ */
+ @Test(expected = ProcessingException.class)
+ public void testAbortingFilter() {
+ final Response response = target().path("simple").request().get();
+ int status = response.getStatus();
+ logger.info("Response status is: " + status);
+ }
+
+ /**
+ * The original reproted scenario with a different Connector.
+ */
+ @Test
+ public void testAbortingFilterWithApacheConnector() {
+ ClientConfig clientConfig = new ClientConfig();
+ clientConfig.connectorProvider(new ApacheConnectorProvider());
+ Client client = ClientBuilder.newClient(clientConfig);
+
+ final Response response = client.target(getBaseUri()).path("/simple").request().get();
+ int status = response.getStatus();
+ logger.info("Response status is: " + status);
+ assertEquals(status, Response.Status.UNAUTHORIZED.getStatusCode());
+ }
+
+ /**
+ * This test shows, that the behaviour is not caused by the use of the filters, but by the response content itself.
+ */
+ @Test(expected = ProcessingException.class)
+ public void testDirectResponse() {
+ final Response response = target().path("simple/direct").request().get();
+ int status = response.getStatus();
+ logger.info("Response status is: " + status);
+ }
+
+ /**
+ * Dynamically launch specific filters for specific resource methods
+ */
+ public static class FilterDynamicBinding implements DynamicFeature {
+ @Override
+ public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+ if (SimpleTestResource.class.equals(resourceInfo.getResourceClass())) {
+ String methodName = resourceInfo.getResourceMethod().getName();
+ if (methodName.contains("simpleResponseTest")) {
+ context.register(AbortingResponseFilter.class);
+ logger.info("Aborting will take place in ResponseFilter.");
+ } else if (methodName.contains("simpleTest")) {
+ context.register(AbortingFilter.class);
+ logger.info("Aborting will take place in RequestFilter.");
+ } else {
+ logger.info("Response will not be aborted.");
+ }
+ }
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AcceptMediaTypeProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AcceptMediaTypeProviderTest.java
new file mode 100644
index 0000000..13ae165
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AcceptMediaTypeProviderTest.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+import org.glassfish.jersey.message.internal.AcceptableMediaType;
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author unknown
+ */
+public class AcceptMediaTypeProviderTest {
+
+ @Test
+ public void testOneMediaType() throws Exception {
+ String header = "application/xml";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(1, l.size());
+
+ MediaType m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testOneMediaTypeWithParameters() throws Exception {
+ String header = "application/xml;charset=utf8";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(1, l.size());
+
+ MediaType m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ assertTrue(m.getParameters().containsKey("charset"));
+ assertEquals("utf8", m.getParameters().get("charset"));
+ }
+
+ @Test
+ public void testMultipleMediaType() throws Exception {
+ String header = "application/xml, text/xml, text/html";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMultipleMediaTypeWithQuality() throws Exception {
+ String header = "application/xml;q=0.1, text/xml;q=0.2, text/html;q=0.3";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testHttpURLConnectionAcceptHeader() throws Exception {
+ String header = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(5, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("image", m.getType());
+ assertEquals("gif", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("image", m.getType());
+ assertEquals("jpeg", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testFirefoxAcceptHeader() throws Exception {
+ String header = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(7, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xhtml+xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("image", m.getType());
+ assertEquals("png", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(6);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testWithStarAcceptHeader() throws Exception {
+ String header = "application/xml;q=0.1, text/xml;q=0.2, *;q=0.3";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifity() throws Exception {
+ String header = "*/*, text/*, text/plain";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityWithQuality() throws Exception {
+ String header = "*/*, */*;q=0.5, text/*, text/*;q=0.5, text/plain, text/plain;q=0.5";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ assertEquals(6, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityHTTPExample1() throws Exception {
+ String header = "text/*, text/html, text/html;level=1, */*";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityHTTPExample2() throws Exception {
+ String header = "text/*, text/html;level=1, text/html, */*";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testHttpURLConnectionAcceptHeaderWithPrority() throws Exception {
+ String header = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
+
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header,
+ HttpHeaderReader.readQualitySourceMediaType(MediaType.TEXT_HTML));
+
+ assertEquals(5, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("image", m.getType());
+ assertEquals("gif", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("image", m.getType());
+ assertEquals("jpeg", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testFirefoxAcceptHeaderWithPrority() throws Exception {
+ String header = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(
+ header, HttpHeaderReader.readQualitySourceMediaType("text/html;qs=1"));
+
+ assertEquals(7, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("application", m.getType());
+ assertEquals("xhtml+xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("image", m.getType());
+ assertEquals("png", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(6);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testFirefoxAcceptHeaderWithPrority2() throws Exception {
+ String header = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
+ List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(
+ header,
+ HttpHeaderReader.readQualitySourceMediaType(new String[]{"text/html;qs=0.8", "application/xml;qs=0.1"}));
+
+ assertEquals(7, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("application", m.getType());
+ assertEquals("xhtml+xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("image", m.getType());
+ assertEquals("png", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(6);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AnnotationInheritanceTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AnnotationInheritanceTest.java
new file mode 100644
index 0000000..82bb86f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/AnnotationInheritanceTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.Test;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that JAX-RS annotations are correctly inherited according to the specification.
+ *
+ * The annotations on a super-class should take precedence over annotations on an interface.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class AnnotationInheritanceTest extends JerseyTest {
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(
+ Foo.class, Bar.class
+ );
+ }
+
+ public interface SuperFooable extends Fooable {
+ @GET
+ @Path("superFooableWhatsUp")
+ String getWhatsUp();
+ }
+
+ public interface Fooable {
+ @GET
+ @Path("fooableHello")
+ String getHello();
+
+ @GET
+ @Path("fooableHi")
+ String getHi();
+
+ }
+
+ public abstract static class SuperFoo implements SuperFooable {
+ @GET
+ @Path("superFooHello")
+ public String getHello() {
+ return "-WRONG MESSAGE-";
+ }
+
+ // no annotations here this time
+ public String getHi() {
+ return "-WRONG MESSAGE-";
+ }
+ }
+
+ @Path(value = "/foo")
+ public static class Foo extends SuperFoo implements Fooable {
+ public String getHello() {
+ return "Hello!";
+ }
+
+ public String getHi() {
+ return "Hi!";
+ }
+
+ public String getWhatsUp() {
+ return "What's up?";
+ }
+ }
+
+ @Path("hyperBar")
+ public static class HyperBar {
+
+ }
+
+ public static class SuperBar extends HyperBar {
+ }
+
+ @Path("barable")
+ public interface Barable {
+ }
+
+
+ public static class Bar extends SuperBar implements Barable {
+ @GET
+ @Path("bar")
+ public String getBar() {
+ return "bar";
+ }
+ }
+
+ /**
+ * Test that when there are conflicting annotations on the methods, the annotations in the superclass has higher
+ * priority than the one in the interface.
+ */
+ @Test
+ public void testSuperClassPrecedence() {
+ final String superClassResponse = target().path("foo/superFooHello").request(MediaType.TEXT_PLAIN).get(String.class);
+ assertEquals("The path from the super-class annotation should be used instead of the path from interface",
+ "Hello!", superClassResponse);
+
+ final Response ifaceResponse = target().path("foo/fooableHello").request(MediaType.TEXT_PLAIN).get(Response.class);
+ assertEquals("The path defined in the interface annotation should not exist.", 404, ifaceResponse.getStatus());
+ }
+
+ /**
+ * Test that the annotation is inherited from the interface, if it cannot be found in the chain of superclasses.
+ */
+ @Test
+ public void testInterfaceAnnotationInheritance() {
+ final String response = target().path("foo/fooableHi").request(MediaType.TEXT_PLAIN).get(String.class);
+ assertEquals("The path from the super-class annotation should inherited.",
+ "Hi!", response);
+ }
+
+ /**
+ * Test that if the annotation is not found in the chain of superclasses, it is inherited from the interface, that
+ * is "nearest" ito the class. In this particular case - superclasses do not have annotation,
+ * that could be inherited, neither does the interface directly implemented by the class, so the test expects the
+ * annotation to be inherited from the interface of the superclass.
+ */
+ @Test
+ public void testInheritenceFromSuperclassInterface() {
+ final String response = target().path("foo/superFooableWhatsUp").request(MediaType.TEXT_PLAIN).get(String.class);
+ assertEquals("The path from the interface of the superclass should inherited.",
+ "What's up?", response);
+ }
+
+ /**
+ * Test that class-level annotation behave in the similar manner as the method-level annotations, although this
+ * behaviour is not directly specified in the JSR-339 (in the Chapter 3.6., the specification explicitly states
+ * that "Note that inheritance of class or interface annotations is not supported".
+ *
+ * Jersey does support class-level annotations inheritance as its specific behaviour beyond the JSR scope.
+ */
+ @Test
+ public void testClassAnnotationInheritance() {
+ final String superClassResponse = target().path("hyperBar/bar").request(MediaType.TEXT_PLAIN).get(String.class);
+ assertEquals("The path from the superclass annotation should be used instead of the path from interface",
+ "bar", superClassResponse);
+
+ final Response ifaceResponse = target().path("barable/bar").request(MediaType.TEXT_PLAIN).get(Response.class);
+ assertEquals("The path defined in the interface annotation should not exist.", 404, ifaceResponse.getStatus());
+ }
+
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CacheControlImplTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CacheControlImplTest.java
new file mode 100644
index 0000000..678c965
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CacheControlImplTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import javax.ws.rs.core.CacheControl;
+
+import org.glassfish.jersey.message.internal.CacheControlProvider;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Marc Hadley
+ */
+public class CacheControlImplTest {
+
+ @Test
+ public void testToString() {
+ CacheControlProvider p = new CacheControlProvider();
+ CacheControl instance = new CacheControl();
+
+ instance.setNoCache(true);
+ String expResult = "no-cache, no-transform";
+ String result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance.setNoStore(true);
+ expResult = "no-cache, no-store, no-transform";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance.setPrivate(true);
+ expResult = "private, no-cache, no-store, no-transform";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance.getPrivateFields().add("Fred");
+ expResult = "private=\"Fred\", no-cache, no-store, no-transform";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+ instance.getPrivateFields().add("Bob");
+ expResult = "private=\"Fred, Bob\", no-cache, no-store, no-transform";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance = new CacheControl();
+ instance.getCacheExtension().put("key1", "value1");
+ expResult = "no-transform, key1=value1";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+ instance.getCacheExtension().put("key1", "value1 with spaces");
+ expResult = "no-transform, key1=\"value1 with spaces\"";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance.setNoStore(true);
+ expResult = "no-store, no-transform, key1=\"value1 with spaces\"";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+
+ instance = new CacheControl();
+ instance.getCacheExtension().put("key1", null);
+ expResult = "no-transform, key1";
+ result = p.toString(instance);
+ assertEquals(expResult, result);
+ }
+
+ @Test
+ public void testRoundTrip() {
+ checkRoundTrip("no-cache, no-transform");
+ checkRoundTrip("no-cache, no-store, no-transform");
+ checkRoundTrip("private, no-cache, no-store, no-transform");
+ checkRoundTrip("private=\"Fred\", no-cache, no-store, no-transform");
+ checkRoundTrip("private=\"Fred, Bob\", no-cache, no-store, no-transform");
+ checkRoundTrip("no-transform, key1=value1");
+ checkRoundTrip("no-transform, key1=\"value1 with spaces\"");
+ checkRoundTrip("no-store, no-transform, key1=\"value1 with spaces\"");
+ checkRoundTrip("no-transform, key1");
+ checkRoundTrip("must-revalidate, proxy-revalidate");
+ checkRoundTrip("max-age=1, s-maxage=1");
+ }
+
+ private void checkRoundTrip(String s) {
+ CacheControlProvider p = new CacheControlProvider();
+
+ CacheControl cc1 = p.fromString(s);
+ CacheControl cc2 = p.fromString(cc1.toString());
+ cc2.toString();
+
+ cc1.equals(cc2);
+
+ try {
+ assertEquals(cc1, cc2);
+ } catch (RuntimeException ex) {
+ throw ex;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ClientInvocationTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ClientInvocationTest.java
new file mode 100644
index 0000000..200f0ec
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ClientInvocationTest.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.core.GenericType;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * {@link Invocation} E2E API tests.
+ *
+ * @author Michal Gajdos
+ */
+public class ClientInvocationTest extends JerseyTest {
+
+ private static final int INVOCATIONS = 5;
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get() {
+ return "OK";
+ }
+
+ @POST
+ public String post(final String entity) {
+ return entity;
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCalls() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCallsAsString() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCallsAsGenericType() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get(new GenericType<String>() {}), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCallsWithEntity() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity)).readEntity(String.class), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCallsAsStringWithEntity() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity), String.class), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleSyncInvokerCallsAsGenericTypeWithEntity() throws Exception {
+ final Invocation.Builder request = target().request();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity), new GenericType<String>() {}), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCalls() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get().get().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCallsAsString() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get(String.class).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCallsAsGenericType() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(request.get(new GenericType<String>() {}).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCallsWithEntity() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity)).get().readEntity(String.class), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCallsAsStringWithEntity() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity), String.class).get(), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleAsyncInvokerCallsAsGenericTypeWithEntity() throws Exception {
+ final AsyncInvoker request = target().request().async();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final String entity = "Message: " + i;
+ assertThat(request.post(Entity.text(entity), new GenericType<String>() {}).get(), is(entity));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokes() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokesAsString() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokesAsGenericType() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke(new GenericType<String>() {}), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokesWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokesAsStringWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationInvokesAsGenericTypeWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.invoke(new GenericType<String>() {}), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmits() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit().get().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmitsAsString() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit(String.class).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmitsAsGenericType() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit(new GenericType<String>() {}).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleCallbackInvocationSubmits() throws Exception {
+ final Invocation invocation = target().request().buildGet();
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<String> response = new AtomicReference<>();
+
+ invocation.submit(new InvocationCallback<String>() {
+ @Override
+ public void completed(final String s) {
+ response.set(s);
+ latch.countDown();
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
+ response.set(throwable.getMessage());
+ latch.countDown();
+ }
+ });
+
+ latch.await(5, TimeUnit.SECONDS);
+ assertThat(response.get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmitsWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit().get().readEntity(String.class), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmitsAsStringWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit(String.class).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleInvocationSubmitsAsGenericTypeWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ assertThat(invocation.submit(new GenericType<String>() {}).get(), is("OK"));
+ }
+ }
+
+ @Test
+ public void testMultipleCallbackInvocationSubmitsWithEntity() throws Exception {
+ final Invocation invocation = target().request().buildPost(Entity.text("OK"));
+
+ for (int i = 0; i < INVOCATIONS; i++) {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<String> response = new AtomicReference<>();
+
+ invocation.submit(new InvocationCallback<String>() {
+ @Override
+ public void completed(final String s) {
+ response.set(s);
+ latch.countDown();
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
+ response.set(throwable.getMessage());
+ latch.countDown();
+ }
+ });
+
+ latch.await(5, TimeUnit.SECONDS);
+ assertThat(response.get(), is("OK"));
+ }
+ }
+}
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConstructorSelectionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConstructorSelectionTest.java
new file mode 100644
index 0000000..eac4d1d
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConstructorSelectionTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Test to verify the proper constructor is selected.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ConstructorSelectionTest extends JerseyTest {
+
+ /**
+ * A resource with multiple constructors.
+ */
+ @Path("resource-test")
+ public static class MultipleConstructorResource {
+ private HttpHeaders headers;
+ private UriInfo info;
+ private Application application;
+ private Request request;
+ private Providers provider;
+
+ public MultipleConstructorResource(){
+ }
+
+ public MultipleConstructorResource(@Context HttpHeaders headers){
+ this.headers = headers;
+ }
+
+
+ public MultipleConstructorResource(@Context HttpHeaders headers,
+ @Context UriInfo info){
+ this.headers = headers;
+ this.info = info;
+ }
+
+ public MultipleConstructorResource(@Context HttpHeaders headers,
+ @Context UriInfo info,
+ @Context Application application){
+ this.application = application;
+ this.headers = headers;
+ this.info = info;
+ }
+
+ public MultipleConstructorResource(@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 MultipleConstructorResource(@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
+ public Response isUsedConstructorWithMostAttributes(){
+ boolean ok = application != null;
+ ok &= headers != null;
+ ok &= info != null;
+ ok &= request != null;
+ ok &= provider == null;
+ Response.Status status = ok ? Response.Status.OK : Response.Status.INTERNAL_SERVER_ERROR;
+ return Response.status(status).build();
+ }
+ }
+
+ /**
+ * Provider with multiple constructors.
+ */
+ @Provider
+ @Consumes(MediaType.TEXT_PLAIN)
+ public static class StringReader implements MessageBodyReader<String> {
+ private HttpHeaders headers;
+ private UriInfo info;
+ private Application application;
+ private Request request;
+ private Providers providers;
+
+ protected StringReader(@Context HttpHeaders headers, @Context UriInfo info,
+ @Context Application application, @Context Request request,
+ @Context Providers providers) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ this.request = request;
+ this.providers = providers;
+ }
+
+ public StringReader(@Context HttpHeaders headers, @Context UriInfo info,
+ @Context Application application, @Context Request request) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ this.request = request;
+ }
+
+ public StringReader(@Context HttpHeaders headers, @Context UriInfo info,
+ @Context Application application) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ this.application = application;
+ }
+
+ public StringReader(@Context HttpHeaders headers, @Context UriInfo info) {
+ super();
+ this.headers = headers;
+ this.info = info;
+ }
+
+ public StringReader(@Context HttpHeaders headers) {
+ super();
+ this.headers = headers;
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ if (headers == null || info == null || application == null || request == null || providers != null) {
+ return "fail";
+ }
+ return "pass";
+ }
+ }
+
+ @Path("provider-test")
+ public static class ProviderResource {
+
+ @POST
+ public String echo(String entity) {
+ return entity;
+ }
+
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MultipleConstructorResource.class, ProviderResource.class, StringReader.class);
+ }
+
+ /**
+ * JERSEY-1529 reproducer.
+ */
+ @Test
+ public void testResourceConstructorSelection() {
+ final Response response = target("resource-test").request().get();
+
+ assertNotNull("Returned response must not be null.", response);
+ assertEquals("Resource constructor with most arguments has not been selected.", 200, response.getStatus());
+ }
+
+ /**
+ * JERSEY-1712 reproducer.
+ */
+ @Test
+ public void testProviderConstructorSelection() {
+ final Response response = target("provider-test").request().post(Entity.text("echo"));
+
+ assertNotNull("Returned response must not be null.", response);
+ assertEquals(200, response.getStatus());
+ assertEquals("pass", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConsumeProduceTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConsumeProduceTest.java
new file mode 100644
index 0000000..cc94667
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ConsumeProduceTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ */
+public class ConsumeProduceTest {
+ @Consumes({"*/*", "a/*", "b/*", "a/b", "c/d"})
+ class ConsumesClass {
+ }
+
+ @Produces ({"*/*", "a/*", "b/*", "a/b", "c/d"})
+ class ProducesClass {
+ }
+
+ @Test
+ public void testConsumes() {
+ final Consumes c = ConsumesClass.class.getAnnotation(Consumes.class);
+ final List<MediaType> l = MediaTypes.createFrom(c);
+ checkMediaTypes(l);
+ }
+
+ @Test
+ public void testProduces() {
+ final Produces p = ProducesClass.class.getAnnotation(Produces.class);
+ final List<MediaType> l = MediaTypes.createFrom(p);
+ checkMediaTypes(l);
+ }
+
+ @Consumes("*/*, a/*, b/*, a/b, c/d")
+ class ConsumesStringClass {
+ }
+
+ @Produces("*/*, a/*, b/*, a/b, c/d")
+ class ProducesStringClass {
+ }
+
+ @Test
+ public void testConsumesString() {
+ final Consumes c = ConsumesStringClass.class.getAnnotation(Consumes.class);
+ final List<MediaType> l = MediaTypes.createFrom(c);
+ checkMediaTypes(l);
+ }
+
+ @Test
+ public void testProducesString() {
+ final Produces p = ProducesStringClass.class.getAnnotation(Produces.class);
+ final List<MediaType> l = MediaTypes.createFrom(p);
+ checkMediaTypes(l);
+ }
+
+ @Consumes({"*/*, a/*", "b/*, a/b", "c/d"})
+ class ConsumesStringsClass {
+ }
+
+ @Produces({"*/*, a/*", "b/*, a/b", "c/d"})
+ class ProducesStringsClass {
+ }
+
+ @Test
+ public void testConsumesStrings() {
+ final Consumes c = ConsumesStringsClass.class.getAnnotation(Consumes.class);
+ final List<MediaType> l = MediaTypes.createFrom(c);
+ checkMediaTypes(l);
+ }
+
+ @Test
+ public void testProducesStrings() {
+ final Produces p = ProducesStringsClass.class.getAnnotation(Produces.class);
+ final List<MediaType> l = MediaTypes.createFrom(p);
+ checkMediaTypes(l);
+ }
+
+
+ void checkMediaTypes(final List<MediaType> l) {
+ assertEquals(5, l.size());
+ assertEquals("a", l.get(0).getType());
+ assertEquals("b", l.get(0).getSubtype());
+ assertEquals("c", l.get(1).getType());
+ assertEquals("d", l.get(1).getSubtype());
+ assertEquals("a", l.get(2).getType());
+ assertEquals("*", l.get(2).getSubtype());
+ assertEquals("b", l.get(3).getType());
+ assertEquals("*", l.get(3).getSubtype());
+ assertEquals("*", l.get(4).getType());
+ assertEquals("*", l.get(4).getSubtype());
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
new file mode 100644
index 0000000..63f2cd2
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.text.ParseException;
+import java.util.Date;
+
+import org.glassfish.jersey.media.multipart.ContentDisposition;
+import org.glassfish.jersey.message.internal.HttpDateFormat;
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Imran@SmartITEngineering.Com
+ */
+public class ContentDispositionTest {
+
+ protected String contentDispositionType;
+
+ public ContentDispositionTest() {
+ contentDispositionType = "inline";
+ }
+
+ @Test
+ public void testCreate() {
+ ContentDisposition contentDisposition = ContentDisposition.type(null).build();
+
+ assertNotNull(contentDisposition);
+ assertEquals(null, contentDisposition.getType());
+
+ contentDisposition = ContentDisposition.type(contentDispositionType).build();
+
+ assertNotNull(contentDisposition);
+ assertEquals(contentDispositionType, contentDisposition.getType());
+
+ final Date date = new Date();
+ contentDisposition = ContentDisposition.type(contentDispositionType).fileName("test.file")
+ .creationDate(date).modificationDate(date).readDate(date).size(1222).build();
+
+ assertContentDisposition(contentDisposition, date);
+ String header = contentDispositionType;
+
+ try {
+ contentDisposition = new ContentDisposition(contentDisposition.toString());
+ assertNotNull(contentDisposition);
+ contentDisposition = new ContentDisposition(header);
+ assertNotNull(contentDisposition);
+ assertEquals(contentDispositionType, contentDisposition.getType());
+ final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ header = contentDispositionType + ";filename=\"test.file\";creation-date=\""
+ + dateString + "\";modification-date=\"" + dateString + "\";read-date=\""
+ + dateString + "\";size=1222";
+
+ contentDisposition = new ContentDisposition(header);
+ assertContentDisposition(contentDisposition, date);
+ contentDisposition = new ContentDisposition(HttpHeaderReader.newInstance(header), true);
+ assertContentDisposition(contentDisposition, date);
+ } catch (final ParseException ex) {
+ fail(ex.getMessage());
+ }
+ try {
+ new ContentDisposition((HttpHeaderReader) null, true);
+ fail("NullPointerException was expected to be thrown.");
+ } catch (final ParseException exception) {
+ fail(exception.getMessage());
+ } catch (final NullPointerException exception) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testToString() {
+ final Date date = new Date();
+ final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("test.file")
+ .creationDate(date).modificationDate(date).readDate(date).size(1222).build();
+ final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\""
+ + dateString + "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222";
+ assertEquals(header, contentDisposition.toString());
+ }
+
+ protected void assertContentDisposition(final ContentDisposition contentDisposition, Date date) {
+ assertNotNull(contentDisposition);
+ assertEquals(contentDispositionType, contentDisposition.getType());
+ assertEquals("test.file", contentDisposition.getFileName());
+ assertEquals(date.toString(), contentDisposition.getModificationDate().toString());
+ assertEquals(date.toString(), contentDisposition.getReadDate().toString());
+ assertEquals(date.toString(), contentDisposition.getCreationDate().toString());
+ assertEquals(1222, contentDisposition.getSize());
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
new file mode 100644
index 0000000..64e1435
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.NewCookie;
+
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marc Hadley
+ */
+public class CookieImplTest {
+
+ @Test
+ public void testCookieToString() {
+ Cookie cookie = new Cookie("fred", "flintstone");
+ String expResult = "$Version=1;fred=flintstone";
+ assertEquals(expResult, cookie.toString());
+
+ cookie = new Cookie("fred", "flintstone", "/path", null);
+ expResult = "$Version=1;fred=flintstone;$Path=/path";
+ assertEquals(expResult, cookie.toString());
+
+ cookie = new Cookie("fred", "flintstone", "/path", ".sun.com");
+ expResult = "$Version=1;fred=flintstone;$Domain=.sun.com;$Path=/path";
+ assertEquals(expResult, cookie.toString());
+
+ cookie = new Cookie("fred", "flintstone", "/path", ".sun.com", 2);
+ expResult = "$Version=2;fred=flintstone;$Domain=.sun.com;$Path=/path";
+ assertEquals(expResult, cookie.toString());
+ }
+
+ @Test
+ public void testCookieValueOf() {
+ Cookie cookie = Cookie.valueOf("$Version=2;fred=flintstone");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals(2, cookie.getVersion());
+
+ cookie = Cookie.valueOf("$Version=1;fred=flintstone;$Path=/path");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals(1, cookie.getVersion());
+ assertEquals("/path", cookie.getPath());
+
+ cookie = Cookie.valueOf("$Version=1;fred=flintstone;$Domain=.sun.com;$Path=/path");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals(1, cookie.getVersion());
+ assertEquals(".sun.com", cookie.getDomain());
+ assertEquals("/path", cookie.getPath());
+ }
+
+ @Test
+ public void testCreateCookies() {
+ String cookieHeader = "fred=flintstone";
+ Map<String, Cookie> cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 1);
+ Cookie c = cookies.get("fred");
+ assertEquals(c.getVersion(), 0);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+
+ cookieHeader = "fred=flintstone,barney=rubble";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 2);
+ c = cookies.get("fred");
+ assertEquals(c.getVersion(), 0);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+ c = cookies.get("barney");
+ assertEquals(c.getVersion(), 0);
+ assertTrue("barney".equals(c.getName()));
+ assertTrue("rubble".equals(c.getValue()));
+
+ cookieHeader = "fred=flintstone;barney=rubble";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 2);
+ c = cookies.get("fred");
+ assertEquals(c.getVersion(), 0);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+ c = cookies.get("barney");
+ assertEquals(c.getVersion(), 0);
+ assertTrue("barney".equals(c.getName()));
+ assertTrue("rubble".equals(c.getValue()));
+
+ cookieHeader = "$Version=1;fred=flintstone;$Path=/path;barney=rubble";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 2);
+ c = cookies.get("fred");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+ assertTrue("/path".equals(c.getPath()));
+ c = cookies.get("barney");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("barney".equals(c.getName()));
+ assertTrue("rubble".equals(c.getValue()));
+
+ cookieHeader = "$Version=1;fred=flintstone;$Path=/path,barney=rubble;$Domain=.sun.com";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 2);
+ c = cookies.get("fred");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+ assertTrue("/path".equals(c.getPath()));
+ c = cookies.get("barney");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("barney".equals(c.getName()));
+ assertTrue("rubble".equals(c.getValue()));
+ assertTrue(".sun.com".equals(c.getDomain()));
+
+ cookieHeader = "$Version=1; fred = flintstone ; $Path=/path, barney=rubble ;$Domain=.sun.com";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 2);
+ c = cookies.get("fred");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("fred".equals(c.getName()));
+ assertTrue("flintstone".equals(c.getValue()));
+ assertTrue("/path".equals(c.getPath()));
+ c = cookies.get("barney");
+ assertEquals(c.getVersion(), 1);
+ assertTrue("barney".equals(c.getName()));
+ assertTrue("rubble".equals(c.getValue()));
+ assertTrue(".sun.com".equals(c.getDomain()));
+ }
+
+ @Test
+ public void testNewCookieToString() {
+ NewCookie cookie = new NewCookie("fred", "flintstone");
+ String expResult = "fred=flintstone;Version=1";
+ assertEquals(expResult, cookie.toString());
+
+ cookie = new NewCookie("fred", "flintstone", null, null, null, 60, false);
+ expResult = "fred=flintstone;Version=1;Max-Age=60";
+ assertEquals(expResult, cookie.toString());
+
+ cookie = new NewCookie("fred", "flintstone", null, null, "a modern stonage family", 60, false);
+ expResult = "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60";
+ assertEquals(expResult, cookie.toString());
+ }
+
+ @Test
+ public void testNewCookieValueOf() {
+ NewCookie cookie = NewCookie.valueOf("fred=flintstone;Version=2");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals(2, cookie.getVersion());
+
+ cookie = NewCookie.valueOf("fred=flintstone;Version=1;Max-Age=60");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals(1, cookie.getVersion());
+ assertEquals(60, cookie.getMaxAge());
+
+ cookie = NewCookie.valueOf("fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60;Secure");
+ assertEquals("fred", cookie.getName());
+ assertEquals("flintstone", cookie.getValue());
+ assertEquals("a modern stonage family", cookie.getComment());
+ assertEquals(1, cookie.getVersion());
+ assertEquals(60, cookie.getMaxAge());
+ assertTrue(cookie.isSecure());
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/EntityTagProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/EntityTagProviderTest.java
new file mode 100644
index 0000000..dc6f80b
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/EntityTagProviderTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import javax.ws.rs.core.EntityTag;
+
+import org.glassfish.jersey.message.internal.EntityTagProvider;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Marc Hadley
+ */
+public class EntityTagProviderTest {
+
+ @Test
+ public void testToStringWeak() {
+ checkToString(new EntityTag("Hello \"World\"", true), "W/\"Hello \\\"World\\\"\"");
+ }
+
+ @Test
+ public void testToStringStrong() {
+ checkToString(new EntityTag("Hello \"World\""), "\"Hello \\\"World\\\"\"");
+ }
+
+ @Test
+ public void testFromStringWeak() throws Exception {
+ checkFromString("W/\"Hello \\\"World\\\"\"", new EntityTag("Hello \"World\"", true));
+ }
+
+ @Test
+ public void testFromStringStrong() throws Exception {
+ checkFromString("\"Hello \\\"World\\\"\"", new EntityTag("Hello \"World\""));
+ }
+
+ private void checkToString(final EntityTag e, final String result) {
+ final EntityTagProvider instance = new EntityTagProvider();
+ assertEquals(result, instance.toString(e));
+ }
+
+ public void checkFromString(final String e, final EntityTag result) throws Exception {
+ final EntityTagProvider instance = new EntityTagProvider();
+ assertEquals(result, instance.fromString(e));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ExceptionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ExceptionTest.java
new file mode 100644
index 0000000..2908b8f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ExceptionTest.java
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.NotAcceptableException;
+import javax.ws.rs.NotAllowedException;
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.NotSupportedException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.RedirectionException;
+import javax.ws.rs.ServerErrorException;
+import javax.ws.rs.ServiceUnavailableException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Exception throwing and handling related tests; such as
+ * {@link WebApplicationException} handling on both server and client side,
+ * proper exception throwing etc.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ExceptionTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ ExceptionDrivenResource.class,
+ ResponseDrivenResource.class,
+ // JERSEY-1532
+ NonWaeThrowingConverter.class,
+ ParamConverterThrowingNonWaeFieldTestResource1.class,
+ ParamConverterThrowingNonWaeFieldTestResource2.class,
+ ParamConverterThrowingNonWaeFieldTestResource3.class,
+ ParamConverterThrowingNonWaeFieldTestResource4.class,
+ ParamConverterThrowingNonWaeFieldTestResource5.class,
+ ParamConverterThrowingNonWaeFieldTestResource6.class,
+ ParamConverterThrowingNonWaeFieldTestResource7.class,
+ ParamConverterThrowingNonWaeFieldTestResource8.class,
+ ParamConverterThrowingNonWaeFieldTestResource9.class,
+ ParamConverterThrowingNonWaeFieldTestResource10.class,
+ ParamConverterThrowingNonWaeMethodTestResource.class,
+ WaeThrowingConverter.class,
+ ParamConverterThrowingWaeFieldTestResource1.class,
+ ParamConverterThrowingWaeFieldTestResource2.class,
+ ParamConverterThrowingWaeFieldTestResource3.class,
+ ParamConverterThrowingWaeFieldTestResource4.class,
+ ParamConverterThrowingWaeFieldTestResource5.class,
+ ParamConverterThrowingWaeFieldTestResource6.class,
+ ParamConverterThrowingWaeFieldTestResource7.class,
+ ParamConverterThrowingWaeFieldTestResource8.class,
+ ParamConverterThrowingWaeFieldTestResource9.class,
+ ParamConverterThrowingWaeFieldTestResource10.class,
+ ParamConverterThrowingWaeMethodTestResource.class
+ );
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+ }
+
+ static final URI testUri = UriBuilder.fromUri("http://jersey.java.net").build();
+
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+ static Map<String, WebApplicationException> ExceptionMAP = new HashMap<String, WebApplicationException>() {{
+ put("301", new RedirectionException(Response.Status.MOVED_PERMANENTLY, testUri));
+ put("302", new RedirectionException(Response.Status.FOUND, testUri));
+ put("303", new RedirectionException(Response.Status.SEE_OTHER, testUri));
+ put("307", new RedirectionException(Response.Status.TEMPORARY_REDIRECT, testUri));
+ put("400", new BadRequestException());
+ put("401", new NotAuthorizedException("challenge"));
+ put("402", new ClientErrorException(402));
+ put("404", new NotFoundException());
+ put("405", new NotAllowedException("OPTIONS"));
+ put("406", new NotAcceptableException());
+ put("415", new NotSupportedException());
+ put("500", new InternalServerErrorException());
+ put("501", new ServerErrorException(501));
+ put("503", new ServiceUnavailableException());
+ }};
+
+ static Map<String, Response> ResponseMAP = new HashMap<String, Response>() {{
+ put("301", Response.status(301).location(testUri).build());
+ put("302", Response.status(302).location(testUri).build());
+ put("303", Response.seeOther(testUri).build());
+ put("307", Response.temporaryRedirect(testUri).build());
+ put("400", Response.status(400).build());
+ put("401", Response.status(401).build());
+ put("402", Response.status(402).build());
+ put("404", Response.status(404).build());
+ put("405", Response.status(405).allow("OPTIONS").build());
+ put("406", Response.status(406).build());
+ put("415", Response.status(415).build());
+ put("500", Response.serverError().build());
+ put("501", Response.status(501).build());
+ put("503", Response.status(503).build());
+ }};
+
+ @Path("exceptionDriven")
+ public static class ExceptionDrivenResource {
+
+ @GET
+ @Path("{status}")
+ public String get(@PathParam("status") String status) {
+ throw ExceptionMAP.get(status);
+ }
+ }
+
+ @Path("responseDriven")
+ public static class ResponseDrivenResource {
+
+ @GET
+ @Path("{status}")
+ public Response get(@PathParam("status") String status) {
+ return ResponseMAP.get(status);
+ }
+ }
+
+ private void _testStatusCode(final String status) {
+ _testStatusCodeViaException("exceptionDriven", status);
+ _testStatusCodeDirectly("exceptionDriven", status);
+ _testStatusCodeViaException("responseDriven", status);
+ _testStatusCodeDirectly("responseDriven", status);
+ }
+
+ private void _testStatusCodeViaException(final String prefix, final String status) {
+
+ final int statusCode = Integer.parseInt(status);
+
+ try {
+
+ target().path(prefix).path(status).request().get(ClientResponse.class);
+ fail("An exception expected");
+ } catch (WebApplicationException ex) {
+ //noinspection ThrowableResultOfMethodCallIgnored
+ assertEquals(ExceptionMAP.get(status).getClass(), ex.getClass());
+
+ final Response response = ex.getResponse();
+ assertEquals(statusCode, response.getStatus());
+
+ if (is3xxCode(statusCode)) {
+ assertNotNull(response.getLocation());
+ }
+ }
+ }
+
+ private void _testStatusCodeDirectly(final String prefix, final String status) {
+ final int statusCode = Integer.parseInt(status);
+ final Response response = target().path(prefix).path(status).request().get();
+ assertEquals(statusCode, response.getStatus());
+ if (is3xxCode(statusCode)) {
+ assertNotNull(response.getLocation());
+ }
+ }
+
+ @Test
+ public void testAllStatusCodes() {
+ for (String status : ExceptionMAP.keySet()) {
+ _testStatusCode(status);
+ }
+ }
+
+ private boolean is3xxCode(final int statusCode) {
+ return 299 < statusCode && statusCode < 400;
+ }
+
+ /**
+ * BEGIN: JERSEY-1532 reproducer code:
+ *
+ * From JAX-RS 2.0 spec, sect. 3.2:
+ * ================================
+ * A WebApplicationException thrown during construction of field or property values using 3 or 4 above
+ * is processed directly as described in Section 3.3.4. Other exceptions thrown during construction of
+ * field or property values using 3 or 4 above are treated as client errors: if the field or property is
+ * annotated with @MatrixParam, @QueryParam or @PathParam then an implementation MUST generate an instance
+ * of NotFoundException (404 status) that wraps the thrown exception and no entity; if the field or property
+ * is annotated with @HeaderParam or @CookieParam then an implementation MUST generate an instance of
+ * BadRequestException (400 status) that wraps the thrown exception and no entity. Exceptions MUST be
+ * processed as described in Section 3.3.4.
+ */
+ public static class NonWaeType {
+ }
+
+ public static class NonWaeException extends RuntimeException {
+ }
+
+ @ParamConverter.Lazy
+ public static class NonWaeThrowingConverter implements ParamConverter<NonWaeType>, ParamConverterProvider {
+
+ @Override
+ public NonWaeType fromString(String value) {
+ throw new NonWaeException();
+ }
+
+ @Override
+ public String toString(NonWaeType value) {
+ throw new NonWaeException();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ if (NonWaeType.class.isAssignableFrom(rawType)) {
+ return (ParamConverter<T>) this;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ @Path("param-converter/non-wae/field/default-matrix")
+ public static class ParamConverterThrowingNonWaeFieldTestResource1 {
+ @DefaultValue("value")
+ @MatrixParam("missing")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/default-path")
+ public static class ParamConverterThrowingNonWaeFieldTestResource2 {
+ @DefaultValue("value")
+ @PathParam("missing")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/default-query")
+ public static class ParamConverterThrowingNonWaeFieldTestResource3 {
+ @DefaultValue("value")
+ @QueryParam("missing")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/default-header")
+ public static class ParamConverterThrowingNonWaeFieldTestResource4 {
+ @DefaultValue("value")
+ @HeaderParam("missing")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/default-cookie")
+ public static class ParamConverterThrowingNonWaeFieldTestResource5 {
+ @DefaultValue("value")
+ @CookieParam("missing")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/matrix")
+ public static class ParamConverterThrowingNonWaeFieldTestResource6 {
+ @MatrixParam("test")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/path/{test}")
+ public static class ParamConverterThrowingNonWaeFieldTestResource7 {
+ @PathParam("test")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/query")
+ public static class ParamConverterThrowingNonWaeFieldTestResource8 {
+ @QueryParam("test")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/header")
+ public static class ParamConverterThrowingNonWaeFieldTestResource9 {
+ @HeaderParam("test")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/field/cookie")
+ public static class ParamConverterThrowingNonWaeFieldTestResource10 {
+ @CookieParam("test")
+ private NonWaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/non-wae/method")
+ public static class ParamConverterThrowingNonWaeMethodTestResource {
+
+ @GET
+ @Path("default-matrix")
+ public Response defaultMatrixTest(@DefaultValue("value") @MatrixParam("missing") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-path")
+ public Response defaultPathTest(@DefaultValue("value") @PathParam("missing") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-query")
+ public Response defaultQueryTest(@DefaultValue("value") @QueryParam("missing") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-header")
+ public Response defaultHeaderTest(@DefaultValue("value") @HeaderParam("missing") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-cookie")
+ public Response defaultCookieTest(@DefaultValue("value") @CookieParam("missing") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("matrix")
+ public Response matrixTest(@MatrixParam("test") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("path/{test}")
+ public Response pathTest(@PathParam("test") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("query")
+ public Response queryTest(@QueryParam("test") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("header")
+ public Response headerTest(@HeaderParam("test") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("cookie")
+ public Response cookieTest(@CookieParam("test") NonWaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Test
+ public void testNonWaeExceptionThrownFromParamConverter() {
+ final WebTarget target = target("param-converter/non-wae/");
+
+ testSingle("field-default-matrix", 404, target.path("field/default-matrix").request());
+ testSingle("field-default-path", 404, target.path("field/default-path").request());
+ testSingle("field-default-query", 404, target.path("field/default-query").request());
+ testSingle("field-default-header", 400, target.path("field/default-header").request());
+ testSingle("field-default-cookie", 400, target.path("field/default-cookie").request());
+
+ testSingle("field-matrix", 404, target.path("field/matrix;test=value").request());
+ testSingle("field-path", 404, target.path("field/path/value").request());
+ testSingle("field-query", 404, target.path("field/query").queryParam("test", "value").request());
+ testSingle("field-header", 400, target.path("field/header").request().header("test", "value"));
+ testSingle("field-cookie", 400, target.path("field/cookie").request().cookie("test", "value"));
+
+ testSingle("method-default-matrix", 404, target.path("method/default-matrix").request());
+ testSingle("method-default-path", 404, target.path("method/default-path").request());
+ testSingle("method-default-query", 404, target.path("method/default-query").request());
+ testSingle("method-default-header", 400, target.path("method/default-header").request());
+ testSingle("method-default-cookie", 400, target.path("method/default-cookie").request());
+
+ testSingle("method-matrix", 404, target.path("method/matrix;test=value").request());
+ testSingle("method-path", 404, target.path("method/path/value").request());
+ testSingle("method-query", 404, target.path("method/query").queryParam("test", "value").request());
+ testSingle("method-header", 400, target.path("method/header").request().header("test", "value"));
+ testSingle("method-cookie", 400, target.path("method/cookie").request().cookie("test", "value"));
+ }
+
+ public static class WaeType {
+ }
+
+ @ParamConverter.Lazy
+ public static class WaeThrowingConverter implements ParamConverter<WaeType>, ParamConverterProvider {
+
+ @Override
+ public WaeType fromString(String value) {
+ throw new WebApplicationException(555);
+ }
+
+ @Override
+ public String toString(WaeType value) {
+ throw new WebApplicationException(555);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+ if (WaeType.class.isAssignableFrom(rawType)) {
+ return (ParamConverter<T>) this;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ @Path("param-converter/wae/field/default-matrix")
+ public static class ParamConverterThrowingWaeFieldTestResource1 {
+ @DefaultValue("value")
+ @MatrixParam("missing")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/default-path")
+ public static class ParamConverterThrowingWaeFieldTestResource2 {
+ @DefaultValue("value")
+ @PathParam("missing")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/default-query")
+ public static class ParamConverterThrowingWaeFieldTestResource3 {
+ @DefaultValue("value")
+ @QueryParam("missing")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/default-header")
+ public static class ParamConverterThrowingWaeFieldTestResource4 {
+ @DefaultValue("value")
+ @HeaderParam("missing")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/default-cookie")
+ public static class ParamConverterThrowingWaeFieldTestResource5 {
+ @DefaultValue("value")
+ @CookieParam("missing")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/matrix")
+ public static class ParamConverterThrowingWaeFieldTestResource6 {
+ @MatrixParam("test")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/path/{test}")
+ public static class ParamConverterThrowingWaeFieldTestResource7 {
+ @PathParam("test")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/query")
+ public static class ParamConverterThrowingWaeFieldTestResource8 {
+ @QueryParam("test")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/header")
+ public static class ParamConverterThrowingWaeFieldTestResource9 {
+ @HeaderParam("test")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/field/cookie")
+ public static class ParamConverterThrowingWaeFieldTestResource10 {
+ @CookieParam("test")
+ private WaeType field;
+
+ @GET
+ public Response get() {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Path("param-converter/wae/method")
+ public static class ParamConverterThrowingWaeMethodTestResource {
+
+ @GET
+ @Path("default-matrix")
+ public Response defaultMatrixTest(@DefaultValue("value") @MatrixParam("missing") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-path")
+ public Response defaultPathTest(@DefaultValue("value") @PathParam("missing") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-query")
+ public Response defaultQueryTest(@DefaultValue("value") @QueryParam("missing") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-header")
+ public Response defaultHeaderTest(@DefaultValue("value") @HeaderParam("missing") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("default-cookie")
+ public Response defaultCookieTest(@DefaultValue("value") @CookieParam("missing") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("matrix")
+ public Response matrixTest(@MatrixParam("test") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("path/{test}")
+ public Response pathTest(@PathParam("test") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("query")
+ public Response queryTest(@QueryParam("test") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("header")
+ public Response headerTest(@HeaderParam("test") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+
+ @GET
+ @Path("cookie")
+ public Response cookieTest(@CookieParam("test") WaeType param) {
+ return Response.status(599).entity("This method should not be invoked").build();
+ }
+ }
+
+ @Test
+ public void testWaeExceptionThrownFromParamConverter() {
+ final WebTarget target = target("param-converter/wae/");
+
+ testSingle("field-default-matrix", 555, target.path("field/default-matrix").request());
+ testSingle("field-default-path", 555, target.path("field/default-path").request());
+ testSingle("field-default-query", 555, target.path("field/default-query").request());
+ testSingle("field-default-header", 555, target.path("field/default-header").request());
+ testSingle("field-default-cookie", 555, target.path("field/default-cookie").request());
+
+ testSingle("field-matrix", 555, target.path("field/matrix;test=value").request());
+ testSingle("field-path", 555, target.path("field/path/value").request());
+ testSingle("field-query", 555, target.path("field/query").queryParam("test", "value").request());
+ testSingle("field-header", 555, target.path("field/header").request().header("test", "value"));
+ testSingle("field-cookie", 555, target.path("field/cookie").request().cookie("test", "value"));
+
+ testSingle("method-default-matrix", 555, target.path("method/default-matrix").request());
+ testSingle("method-default-path", 555, target.path("method/default-path").request());
+ testSingle("method-default-query", 555, target.path("method/default-query").request());
+ testSingle("method-default-header", 555, target.path("method/default-header").request());
+ testSingle("method-default-cookie", 555, target.path("method/default-cookie").request());
+
+ testSingle("method-matrix", 555, target.path("method/matrix;test=value").request());
+ testSingle("method-path", 555, target.path("method/path/value").request());
+ testSingle("method-query", 555, target.path("method/query").queryParam("test", "value").request());
+ testSingle("method-header", 555, target.path("method/header").request().header("test", "value"));
+ testSingle("method-cookie", 555, target.path("method/cookie").request().cookie("test", "value"));
+ }
+
+ private void testSingle(String caseName, int expectedStatus, Invocation.Builder request) {
+ final Response response = request.get();
+ assertEquals("Test of an exception thrown during field/parameter injection [" + caseName + "] failed.",
+ expectedStatus,
+ response.getStatus());
+ }
+ /**
+ * END: JERSEY-1532 reproducer code.
+ */
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
new file mode 100644
index 0000000..9d74547
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.text.ParseException;
+import java.util.Date;
+
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.message.internal.HttpDateFormat;
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Imran@SmartITEngineering.Com
+ */
+public class FormDataContentDispositionTest extends ContentDispositionTest {
+
+ public FormDataContentDispositionTest() {
+ contentDispositionType = "form-data";
+ }
+
+ @Test
+ @Override
+ public void testCreate() {
+ final Date date = new Date();
+ FormDataContentDisposition contentDisposition;
+ contentDisposition = FormDataContentDisposition.name("testData").fileName("test.file").creationDate(date)
+ .modificationDate(date).readDate(date).size(1222).build();
+ assertFormDataContentDisposition(contentDisposition, date);
+ try {
+ final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String header = contentDispositionType + ";filename=\"test.file\";creation-date=\"" + dateString
+ + "\";modification-date=\"" + dateString + "\";read-date=\"" + dateString + "\";size=1222"
+ + ";name=\"testData\"";
+
+ contentDisposition = new FormDataContentDisposition(contentDisposition.toString());
+ assertFormDataContentDisposition(contentDisposition, date);
+ contentDisposition = new FormDataContentDisposition(header);
+ assertFormDataContentDisposition(contentDisposition, date);
+ contentDisposition = new FormDataContentDisposition(HttpHeaderReader.newInstance(header), true);
+ assertFormDataContentDisposition(contentDisposition, date);
+ } catch (final ParseException ex) {
+ fail(ex.getMessage());
+ }
+ try {
+ new FormDataContentDisposition((HttpHeaderReader) null, true);
+ fail("NullPointerException was expected to be thrown.");
+ } catch (final ParseException exception) {
+ fail(exception.getMessage());
+ } catch (final NullPointerException exception) {
+ //expected
+ }
+ try {
+ new FormDataContentDisposition("form-data;filename=\"test.file\"");
+ fail("IllegalArgumentException was expected to be thrown.");
+ } catch (final ParseException exception) {
+ fail(exception.getMessage());
+ } catch (final IllegalArgumentException exception) {
+ //expected
+ }
+ try {
+ FormDataContentDisposition.name(null).build();
+ fail("IllegalArgumentException was expected to be thrown.");
+ } catch (final IllegalArgumentException exception) {
+ //expected
+ } catch (final Exception exception) {
+ fail(exception.getMessage());
+ }
+ }
+
+ @Test
+ @Override
+ public void testToString() {
+ final Date date = new Date();
+ final FormDataContentDisposition contentDisposition = FormDataContentDisposition.name("testData")
+ .fileName("test.file").creationDate(date).modificationDate(date)
+ .readDate(date).size(1222).build();
+ final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\"" + dateString
+ + "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222"
+ + "; name=\"testData\"";
+
+ assertEquals(header, contentDisposition.toString());
+ }
+
+ protected void assertFormDataContentDisposition(final FormDataContentDisposition contentDisposition, final Date date) {
+ assertContentDisposition(contentDisposition, date);
+ assertEquals("testData", contentDisposition.getName());
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
new file mode 100644
index 0000000..b0ecbdc
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+import org.glassfish.jersey.message.internal.AcceptableLanguageTag;
+import org.glassfish.jersey.message.internal.AcceptableToken;
+import org.glassfish.jersey.message.internal.HttpDateFormat;
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+import org.glassfish.jersey.message.internal.LanguageTag;
+import org.glassfish.jersey.message.internal.ParameterizedHeader;
+import org.glassfish.jersey.message.internal.Token;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ */
+public class HttpHeaderTest {
+
+ @Test
+ public void testTokens() throws ParseException {
+ final String header = "type / content; a = \"asdsd\"";
+
+ final HttpHeaderReader r = HttpHeaderReader.newInstance(header);
+ while (r.hasNext()) {
+ r.next();
+ }
+ }
+
+ @Test
+ public void testMediaType() throws ParseException {
+ final String mimeType = "application/xml;charset=UTF-8";
+ MediaType.valueOf(mimeType);
+ }
+
+ @Test
+ public void testLanguageTag() throws ParseException {
+ final String languageTag = "en-US";
+ new LanguageTag(languageTag);
+ }
+
+ @Test
+ public void testAcceptableLanguageTag() throws ParseException {
+ final String languageTag = "en-US;q=0.123";
+ new AcceptableLanguageTag(languageTag);
+ }
+
+ @Test
+ public void testAcceptableLanguageTagList() throws Exception {
+ final String languageTags = "en-US;q=0.123, fr;q=0.2, en;q=0.3, *;q=0.01";
+ final List<AcceptableLanguageTag> l = HttpHeaderReader.readAcceptLanguage(languageTags);
+ assertEquals("en", l.get(0).getTag());
+ assertEquals("fr", l.get(1).getTag());
+ assertEquals("en-US", l.get(2).getTag());
+ assertEquals("*", l.get(3).getTag());
+ }
+
+ @Test
+ public void testToken() throws ParseException {
+ final String token = "gzip";
+ new Token(token);
+ }
+
+ @Test
+ public void testAcceptableToken() throws ParseException {
+ final String token = "gzip;q=0.123";
+ new AcceptableToken(token);
+ }
+
+ @Test
+ public void testAcceptableTokenList() throws Exception {
+ final String tokens = "gzip;q=0.123, compress;q=0.2, zlib;q=0.3, *;q=0.01";
+ final List<AcceptableToken> l = HttpHeaderReader.readAcceptToken(tokens);
+ assertEquals("zlib", l.get(0).getToken());
+ assertEquals("compress", l.get(1).getToken());
+ assertEquals("gzip", l.get(2).getToken());
+ assertEquals("*", l.get(3).getToken());
+ }
+
+ @Test
+ public void testDateParsing() throws ParseException {
+ final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
+ final String date_RFC1036 = "Sunday, 06-Nov-94 08:49:37 GMT";
+ final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
+
+ HttpHeaderReader.readDate(date_RFC1123);
+ HttpHeaderReader.readDate(date_RFC1036);
+ HttpHeaderReader.readDate(date_ANSI_C);
+ }
+
+ @Test
+ public void testDateFormatting() throws ParseException {
+ final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
+ final Date date = HttpHeaderReader.readDate(date_RFC1123);
+
+ final String date_formatted = HttpDateFormat.getPreferredDateFormat().format(date);
+ assertEquals(date_RFC1123, date_formatted);
+ }
+
+ @Test
+ public void testParameterizedHeader() throws ParseException {
+ ParameterizedHeader ph = new ParameterizedHeader("a");
+ assertEquals("a", ph.getValue());
+
+ ph = new ParameterizedHeader("a/b");
+ assertEquals("a/b", ph.getValue());
+
+ ph = new ParameterizedHeader(" a / b ");
+ assertEquals("a/b", ph.getValue());
+
+ ph = new ParameterizedHeader("");
+ assertEquals("", ph.getValue());
+
+ ph = new ParameterizedHeader(";");
+ assertEquals("", ph.getValue());
+ assertEquals(0, ph.getParameters().size());
+
+ ph = new ParameterizedHeader(";;;");
+ assertEquals("", ph.getValue());
+ assertEquals(0, ph.getParameters().size());
+
+ ph = new ParameterizedHeader(" ; ; ; ");
+ assertEquals("", ph.getValue());
+ assertEquals(0, ph.getParameters().size());
+
+ ph = new ParameterizedHeader("a;x=1;y=2");
+ assertEquals("a", ph.getValue());
+ assertEquals(2, ph.getParameters().size());
+ assertEquals("1", ph.getParameters().get("x"));
+ assertEquals("2", ph.getParameters().get("y"));
+
+ ph = new ParameterizedHeader("a ; x=1 ; y=2 ");
+ assertEquals("a", ph.getValue());
+ assertEquals(2, ph.getParameters().size());
+ assertEquals("1", ph.getParameters().get("x"));
+ assertEquals("2", ph.getParameters().get("y"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocaleProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocaleProviderTest.java
new file mode 100644
index 0000000..9bce717
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocaleProviderTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.Locale;
+
+import org.glassfish.jersey.message.internal.LocaleProvider;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Mark Hadley
+ */
+public class LocaleProviderTest {
+ @Test
+ public void testToString() {
+ final LocaleProvider instance = new LocaleProvider();
+ assertEquals("en", instance.toString(new Locale("en")));
+ assertEquals("en-US", instance.toString(new Locale("en", "us")));
+ }
+
+ @Test
+ public void testFromString() throws Exception {
+ final LocaleProvider instance = new LocaleProvider();
+ assertEquals(new Locale("en"), instance.fromString("en"));
+ assertEquals(new Locale("en", "us"), instance.fromString("en-us"));
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderAsyncTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderAsyncTest.java
new file mode 100644
index 0000000..b53f999
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderAsyncTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.net.URI;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.server.ManagedAsync;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test if the location relativer URI is correctly resolved within asynchronous processing cases.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RunWith(ConcurrentRunner.class)
+public class LocationHeaderAsyncTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(LocationHeaderAsyncTest.class.getName());
+ static ExecutorService executor;
+
+ private static final AtomicBoolean executorComparisonFailed = new AtomicBoolean(false);
+ private static final AtomicBoolean interrupted = new AtomicBoolean(false);
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(ResponseTest.class);
+ }
+
+ /**
+ * Prepare test infrastructure.
+ *
+ * In this case it prepares executor thread pool of size one and initializes the thread.
+ * @throws Exception
+ */
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ /* thread pool for custom executor async test */
+ LocationHeaderAsyncTest.executor = Executors.newFixedThreadPool(1);
+
+ // Force the thread to be eagerly instantiated - this prevents the instantiation later and ensures, that the thread
+ // will not be a child thread of the request handling thread, so the thread-local baseUri variable will not be inherited.
+ LocationHeaderAsyncTest.executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ LOGGER.info("Thread pool initialized.");
+ }
+ });
+ }
+
+ /**
+ * Test JAX-RS resource
+ */
+ @SuppressWarnings("VoidMethodAnnotatedWithGET")
+ @Path(value = "/ResponseTest")
+ public static class ResponseTest {
+
+ /* injected request URI for assertions in the resource methods */
+ @Context
+ private UriInfo uriInfo;
+
+ /**
+ * Asynchronous resource method for testing if the URI is absolutized also in case of asynchronous processing;
+ *
+ * The response is created in the separate thread. This tests, that the thread still has access to the request baseUri
+ * thread-local variable in {@link org.glassfish.jersey.message.internal.OutboundJaxrsResponse.Builder}.
+ */
+ @GET
+ @Path("locationAsync")
+ public void locationAsync(@Suspended final AsyncResponse asyncResponse) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ final URI uri = getUriBuilder().segment("locationAsync").build();
+ final Response result = Response.created(uri).build();
+
+ final URI location = result.getLocation();
+ if (uriInfo.getAbsolutePath().equals(location)) {
+ asyncResponse.resume(result);
+ } else {
+ asyncResponse.resume(Response.serverError().entity(location.toString()).build());
+ }
+
+ }
+ }).start();
+ }
+
+ /**
+ * Resource method for async test with custom executor.
+ *
+ * It runs in a thread that was not created within the request scope, so it does not inherit the baseUri thread-local
+ * variable value.
+ * In this case, URI will not be absolutized until calling {@link AsyncResponse#resume(Object)}.
+ */
+ @GET
+ @Path("executorAsync")
+ @ManagedAsync
+ public void executorAsync(@Suspended final AsyncResponse asyncResponse) {
+ LocationHeaderAsyncTest.executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ final URI uri = getUriBuilder().segment("executorAsync").build();
+ final Response result = Response.created(uri).build();
+ asyncResponse.resume(result);
+ if (!uriInfo.getAbsolutePath().equals(result.getLocation())) {
+ executorComparisonFailed.set(true);
+ }
+ }
+ });
+ }
+
+ /**
+ * Placeholder for the suspended async responses;
+ * For the current test a simple static field would be enough, but this is easily extensible;
+ *
+ * This is inspired by the {@link AsyncResponse} javadoc example
+ */
+ private static final BlockingQueue<AsyncResponse> suspended = new ArrayBlockingQueue<>(5);
+
+ /**
+ * Start of the async test - stores the asynchronous response object
+ */
+ @GET
+ @Path("locationAsyncStart")
+ public void locationAsyncStart(@Suspended final AsyncResponse asyncResponse) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ suspended.put(asyncResponse);
+ } catch (final InterruptedException e) {
+ asyncResponse.cancel();
+ Thread.currentThread().interrupt();
+ interrupted.set(true);
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * Finish of the async test - creates a response, checks the location header and resumes the asyncResponse
+ * @return true if the URI was correctly absolutized, false if the URI is relative or differs from the expected URI
+ */
+ @GET
+ @Path("locationAsyncFinish")
+ public Boolean locationAsyncFinish() throws InterruptedException {
+ final AsyncResponse asyncResponse = suspended.poll(2000, TimeUnit.MILLISECONDS);
+
+ final URI uri = getUriBuilder().segment("locationAsyncFinish").build();
+ final Response result = Response.created(uri).build();
+ final boolean wasEqual = result.getLocation().equals(uriInfo.getAbsolutePath());
+
+ asyncResponse.resume(result);
+ return wasEqual;
+ }
+
+ /** Return UriBuilder with base pre-set {@code /ResponseTest} uri segment for this resource.
+ *
+ * @return UriBuilder
+ */
+ private UriBuilder getUriBuilder() {
+ return UriBuilder.fromResource(ResponseTest.class);
+ }
+ }
+
+ /**
+ * Basic asynchronous testcase; checks if the URI is correctly absolutized also within a separate thread during
+ * async processing
+ */
+ @Test
+ public void testAsync() {
+ final String expectedUri = getBaseUri() + "ResponseTest/locationAsync";
+ final Response response = target().path("ResponseTest/locationAsync").request().get(Response.class);
+
+ final String msg = String.format("Comparison failed in the resource method. \nExpected: %1$s\nActual: %2$s",
+ expectedUri, response.readEntity(String.class));
+ assertNotEquals(msg, response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals(expectedUri, location);
+ }
+
+ /**
+ * Test with a thread from thread-pool (created out of request scope)
+ */
+ @Test
+ public void testExecutorAsync() {
+ final Response response = target().path("ResponseTest/executorAsync").request().get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertFalse("The comparison failed in the resource method.", executorComparisonFailed.get());
+ assertEquals(getBaseUri() + "ResponseTest/executorAsync", location);
+ }
+
+ /**
+ * Asynchronous testcase split over two distinct requests
+ */
+ @Test
+ public void testSeparatedAsync() throws ExecutionException, InterruptedException {
+ final Future<Response> futureResponse = target().path("ResponseTest/locationAsyncStart").request().async().get();
+ final Boolean result = target().path("ResponseTest/locationAsyncFinish").request().get(Boolean.class);
+ assertFalse("Thread was interrupted on inserting into blocking queue.", interrupted.get());
+ assertTrue(result);
+
+ final Response response = futureResponse.get();
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri() + "ResponseTest/locationAsyncFinish", location);
+ }
+}
+
+
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderBasicTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderBasicTest.java
new file mode 100644
index 0000000..767e2e0
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderBasicTest.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.net.URI;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Test if the location relative URI is correctly resolved within basic cases.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RunWith(ConcurrentRunner.class)
+public class LocationHeaderBasicTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(LocationHeaderBasicTest.class.getName());
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(ResponseTest.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ super.configureClient(config);
+ config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+ }
+
+ /**
+ * Test JAX-RS resource
+ */
+ @Path(value = "/ResponseTest")
+ public static class ResponseTest {
+
+ /* injected request URI for assertions in the resource methods */
+ @Context
+ private UriInfo uriInfo;
+
+ /**
+ * Resource method for the basic uri conversion test
+ * @return test response with relative location uri
+ */
+ @GET
+ @Path("location")
+ public Response locationTest() {
+ final URI uri = URI.create("location");
+ LOGGER.info("URI Created in the resource method > " + uri);
+ return Response.created(uri).build();
+ }
+
+ /**
+ * Resource method for the test with null location
+ * @return test response with null location uri
+ */
+ @GET
+ @Path("locationNull")
+ public Response locationTestNull() {
+ return Response.created(null).build();
+ }
+
+ /**
+ * Resource method for the test with entity containing response
+ * @return test response with relative uri and with entity
+ */
+ @GET
+ @Path("locationWithBody")
+ @Produces("text/plain")
+ public Response locationTestWithBody() {
+ final URI uri = URI.create("locationWithBody");
+ return Response.created(uri).entity("Return from locationWithBody").type("text/plain").build();
+ }
+
+ /**
+ * Resource method for direct test - location header is checked immediately after calling Response.created() and
+ * the result is returned as a boolean response instead of returning the ({@link Response}) type and checking the
+ * header in the calling test method. This isolates the influence of absolutization routine performed in the
+ * ({@link org.glassfish.jersey.server.ServerRuntime} before closing the stream.
+ *
+ * @return true if URI is absolutized correctly, false if the URI remains relative (or does not match the expected one).
+ */
+ @GET
+ @Path("locationDirect")
+ @Produces("text/plain")
+ public Boolean locationDirectTest() {
+ final URI uri = getUriBuilder().segment("locationDirect").build();
+ final Response response = Response.created(uri).build();
+ return response.getLocation().equals(uriInfo.getAbsolutePath());
+ }
+
+
+
+
+ /**
+ * Resource method for testing correct baseUri and request overwrite in the prematching filter.
+ * Should never be called by the test, as {@link ResponseTest#redirectedUri()} should be called instead.
+ */
+ @GET
+ @Path("filterChangedBaseUri")
+ public Response locationWithChangedBaseUri() {
+ fail("Method should not expected to be called, as prematching filter should have changed the request uri.");
+ return Response.created(URI.create("new")).build();
+ }
+
+ /**
+ * Not called by the test directly, but after prematching filter redirect from
+ * {@link ResponseTest#locationWithChangedBaseUri()}.
+ *
+ * @return {@code 201 Created} response with location resolved against new baseUri.
+ */
+ @GET
+ @Path("newUri")
+ public Response redirectedUri() {
+ return Response.created(URI.create("newRedirected")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code seeOther} response.
+ * @return {@code 303 See Other} response with relative URI
+ */
+ @POST
+ @Path("seeOther")
+ @Consumes("text/plain")
+ public Response seeOther() {
+ return Response.seeOther(URI.create("other")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code seeOther} response.
+ * @return {@code 303 See Other} response with relative URI
+ */
+ @GET
+ @Path("seeOtherLeading")
+ public Response seeOtherWithLeadingSlash() {
+ return Response.seeOther(URI.create("/other")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code seeOther} response.
+ * @return {@code 303 See Other} response with relative URI
+ */
+ @GET
+ @Path("seeOtherTrailing")
+ public Response seeOtherWithTrailingSlash() {
+ return Response.seeOther(URI.create("other/")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code temporaryRedirect} response.
+ * @return {@code 307 Temporary Redirect} response with relative URI
+ */
+ @GET
+ @Path("temporaryRedirect")
+ public Response temporaryRedirect() {
+ return Response.temporaryRedirect(URI.create("redirect")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code temporaryRedirect} response.
+ * @return {@code 307 Temporary Redirect} response with relative URI
+ */
+ @GET
+ @Path("temporaryRedirectLeading")
+ public Response temporaryRedirectWithLeadingSlash() {
+ return Response.temporaryRedirect(URI.create("/redirect")).build();
+ }
+
+ /**
+ * Resource method for testing relative URI resolution in case of {@code temporaryRedirect} response.
+ * @return {@code 307 Temporary Redirect} response with relative URI
+ */
+ @GET
+ @Path("temporaryRedirectTrailing")
+ public Response temporaryRedirectWithTrailingSlash() {
+ return Response.temporaryRedirect(URI.create("redirect/")).build();
+ }
+
+ /** Return UriBuilder with base pre-set {@code /ResponseTest} uri segment for this resource.
+ *
+ * @return UriBuilder
+ */
+ private UriBuilder getUriBuilder() {
+ return UriBuilder.fromResource(ResponseTest.class);
+ }
+ }
+
+ /**
+ * Basic test; resource methods returns relative uri, test expects uri to be absolute
+ */
+ @Test
+ public void testConvertRelativeUriToAbsolute() {
+ checkResource("ResponseTest/location", "location");
+ // checkResource("ResponseTest/location");
+ }
+
+ /**
+ * Test with entity; most of the HTTP 201 Created responses do not contain any body, just headers.
+ * This test ensures, that the uri conversion works even in case when entity is present.
+ */
+ @Test
+ public void testAbsoluteUriWithEntity() {
+ final Response response = checkResource("ResponseTest/locationWithBody", "locationWithBody");
+ assertNotNull(response.getEntity());
+ }
+
+
+ /**
+ * Test with null location;
+ * Ensures, that the null location is processed correctly.
+ */
+ @Test
+ public void testNullLocation() {
+ final Response response = target().path("ResponseTest/locationNull").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertNull("Location header should be absolute URI", location);
+ }
+
+ /**
+ * Tests if the URI is absolutized in the Response directly after Response.Builder.created() is called
+ */
+ @Test
+ public void testConversionDirectly() {
+ final Boolean result = target().path("ResponseTest/locationDirect").request(MediaType.TEXT_PLAIN).get(Boolean.class);
+ assertTrue(result);
+ }
+
+ @Test
+ public void testSeeOther() {
+ Response response = target().path("ResponseTest/seeOther").request()
+ .post(Entity.entity("TEXT", MediaType.TEXT_PLAIN_TYPE));
+ String location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "other", location);
+
+ response = target().path("ResponseTest/seeOtherLeading").request(MediaType.TEXT_PLAIN).get(Response.class);
+ location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "other", location);
+
+ response = target().path("ResponseTest/seeOtherTrailing").request(MediaType.TEXT_PLAIN).get(Response.class);
+ location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "other/", location);
+ }
+
+ @Test
+ public void testTemporaryRedirect() {
+ Response response = target().path("ResponseTest/temporaryRedirect").request(MediaType.TEXT_PLAIN).get(Response.class);
+ String location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "redirect", location);
+
+ response = target().path("ResponseTest/temporaryRedirectLeading").request(MediaType.TEXT_PLAIN).get(Response.class);
+ location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "redirect", location);
+
+ response = target().path("ResponseTest/temporaryRedirectTrailing").request(MediaType.TEXT_PLAIN).get(Response.class);
+ location = response.getHeaderString(HttpHeaders.LOCATION);
+ assertEquals(getBaseUri().toString() + "redirect/", location);
+ }
+
+ private Response checkResource(final String resourcePath, final String expectedRelativeUri) {
+ final Response response = target().path(resourcePath).request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals(getBaseUri() + expectedRelativeUri, location);
+ return response;
+ }
+}
+
+
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderFiltersTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderFiltersTest.java
new file mode 100644
index 0000000..d6975ac
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderFiltersTest.java
@@ -0,0 +1,594 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.Test;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Test if the location response header relative URI is correctly resolved within complex cases with interceptors, filters,
+ * exception mappers, etc.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class LocationHeaderFiltersTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(LocationHeaderBasicTest.class.getName());
+
+ static ExecutorService executor;
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(
+ MyTest.class,
+ LocationManipulationDynamicBinding.class,
+ AbortingPreMatchingRequestFilter.class,
+ BaseUriChangingPreMatchingFilter.class,
+ TestExceptionMapper.class
+ );
+ }
+
+ /**
+ * Prepare test infrastructure.
+ *
+ * In this case it prepares executor thread pool of size one and initializes the thread.
+ * @throws Exception
+ */
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ /* thread pool for custom executor async test */
+ LocationHeaderFiltersTest.executor = Executors.newFixedThreadPool(1);
+
+ // Force the thread to be eagerly instantiated - this prevents the instantiation later and ensures, that the thread
+ // will not be a child thread of the request handling thread, so the thread-local baseUri variable will not be inherited.
+ LocationHeaderFiltersTest.executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ LOGGER.info("Thread pool initialized.");
+ }
+ });
+ }
+
+
+ /**
+ * Test JAX-RS resource
+ */
+ @SuppressWarnings("VoidMethodAnnotatedWithGET")
+ @Path(value = "/ResponseTest")
+ public static class MyTest {
+
+ /* injected request URI for assertions in the resource methods */
+ @Context
+ private UriInfo uriInfo;
+
+ /**
+ * Resource method for the test with uri rewritten in the filter
+ * @return test response with relative location uri
+ */
+ @GET
+ @Path("locationTestWithFilter")
+ public Response locationTestWithFilter() {
+ final URI uri = URI.create("location");
+ LOGGER.info("URI Created in the resource method > " + uri);
+ return Response.created(uri).build();
+ }
+
+ /**
+ * Resource method for the test with uri rewritten in the interceptor
+ * @return test response with relative location uri and with body
+ * (write interceptors are not triggered for entity-less responses)
+ */
+ @GET
+ @Path("locationWithInterceptor")
+ public Response locationTestWithInterceptor() {
+ final URI uri = URI.create("foo");
+ return Response.created(uri).entity("Return from locationTestWithInterceptor").type("text/plain").build();
+ }
+
+
+ /**
+ * Resource method for testing URI absolutization after the abortion in the post-matching filter.
+ * @return dummy response - this string should never be propagated to the client (the processing chain
+ * will be aborted in the filter before this resource method is even called.
+ * However, it is needed here, because the filter is bound to the resource method name.
+ */
+ @GET
+ @Path("locationAborted")
+ public String locationTestAborted() {
+ assertTrue("The resource method locationTestAborted() should not have been called. The post-matching filter was "
+ + "not configured correctly. ", false);
+ return "DUMMY_RESPONSE"; // this string should never reach the client (the resource method will not be called)
+ }
+
+ /**
+ * Resource method for testing URI absolutization after the abortion in the pre-matching filter.
+ * @return dummy response - this string should never be propagated to the client (the processing chain will be
+ * executorComparisonFailed in the filter before this resource method is even called.
+ * However, it is needed here, because the filter is bound to the resource method name.
+ */
+ @GET
+ @Path("locationAbortedPreMatching")
+ public String locationTestPreMatchingAborted() {
+ assertTrue("The resource method locationTestPreMatchingAborted() should not have been called. The pre-matching "
+ + "filter was not configured correctly. ", false);
+ return "DUMMY_RESPONSE"; // this string should never reach the client (the resource method will not be called)
+ }
+
+ /**
+ * Resource method for the test of ResponseFilters in the sync case.
+ * Returns response with a relative URI, which is than absolutized by Jersey.
+ * Later the {@link UriCheckingResponseFilter} is triggered and checks the URI again - the check itself is done in the
+ * filter.
+ * Based on the result of the check, the filter returns the original status (201 - Created) or an
+ * error status (500 - Internal Server Error) with an error message in the response body.
+ */
+ @GET
+ @Path("responseFilterSync")
+ public Response responseFilterSync() {
+ return Response.created(URI.create("responseFilterSync")).build();
+ }
+
+ /**
+ * Resource method for the test of ResponseFilters in the async case. It runs in the separate thread created on request.
+ *
+ * Returns response with a relative URI, which is than absolutized by Jersey.
+ * Later the {@link UriCheckingResponseFilter} is triggered and checks the URI again - the check itself is done in the
+ * filter.
+ * Based on the result of the check, the filter returns the original status (201 - Created) or an
+ * error status (500 - Internal Server Error) with an error message in the response body.
+ */
+ @GET
+ @Path("responseFilterAsync")
+ public void responseFilterAsync(@Suspended final AsyncResponse asyncResponse) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ final Response result = Response.created(URI.create("responseFilterAsync")).build();
+ asyncResponse.resume(result);
+ }
+ }).start();
+ }
+
+ /**
+ * Resource method for the test of ResponseFilters in the async/executor case. It runs in a thread created out of the
+ * request scope.
+ *
+ * Returns response with a relative URI, which is than absolutized by Jersey.
+ * Later the {@link UriCheckingResponseFilter} is triggered and checks the URI again - the check itself is done in the
+ * filter.
+ * Based on the result of the check, the filter returns the original status (201 - Created) or an
+ * error status (500 - Internal Server Error) with an error message in the response body.
+ */
+ @GET
+ @Path("responseFilterAsyncExecutor")
+ public void responseFilterAsyncExecutor(@Suspended final AsyncResponse asyncResponse) {
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ final Response result =
+ Response.created(URI.create("responseFilterAsyncExecutor")).build();
+ asyncResponse.resume(result);
+ }
+ });
+ }
+
+ /**
+ * Resource method for testing for testing the URI absolutization in the exception mapper in the synchronous case.
+ *
+ * Method always throws {@link WebApplicationException}, which is defined to be handled by {@link TestExceptionMapper}.
+ * The exception mapper then creates the response with relative URI and response is routed
+ * into {@link UriCheckingResponseFilter}, which checks if th URI was correctly absolutized.
+ * @return does not return any response
+ */
+ @GET
+ @Path("exceptionMapperSync")
+ public Response exceptionMapperSync() {
+ throw new WebApplicationException();
+ }
+
+ /**
+ * Resource method for testing for testing the URI absolutization in the exception mapper in the asynchronous case.
+ * New thread is started for the resource method processing.
+ *
+ * Method always "throws" {@link WebApplicationException} (in case of async methods,
+ * the exceptions are not thrown directly, but passed to {@link AsyncResponse#resume(Throwable)}),
+ * which is defined to be handled by {@link TestExceptionMapper}. *
+ * The exception mapper then creates the response with relative URI and response is routed
+ * into {@link UriCheckingResponseFilter}, which checks if th URI was correctly absolutized.
+ */
+ @GET
+ @Path("exceptionMapperAsync")
+ public void exceptionMapperAsync(@Suspended final AsyncResponse asyncResponse) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ asyncResponse.resume(new WebApplicationException());
+ }
+ }).start();
+ }
+
+ /**
+ * Resource method for testing for testing the URI absolutization in the exception mapper in the asynchronous case.
+ * A thread from executor thread pool (created out of request scope) is used for processing the resource method.
+ *
+ * Method always "throws" {@link WebApplicationException} (in case of async methods,
+ * the exceptions are not thrown directly, but passed to {@link AsyncResponse#resume(Throwable)}),
+ * which is defined to be handled by {@link TestExceptionMapper}. *
+ * The exception mapper then creates the response with relative URI and response is routed
+ * into {@link UriCheckingResponseFilter}, which checks if th URI was correctly absolutized.
+ */
+ @GET
+ @Path("exceptionMapperExecutor")
+ public void exceptionMapperExecutor(@Suspended final AsyncResponse asyncResponse) {
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ asyncResponse.resume(new WebApplicationException());
+ }
+ });
+ }
+
+ /**
+ * Resource method for testing correct baseUri and request overwrite in the prematching filter.
+ * Should never be called by the test, as {@link MyTest#redirectedUri()} should be called instead.
+ */
+ @GET
+ @Path("filterChangedBaseUri")
+ public Response locationWithChangedBaseUri() {
+ fail("Method should not expected to be called, as prematching filter should have changed the request uri.");
+ return Response.created(URI.create("new")).build();
+ }
+
+ /**
+ * Not called by the test directly, but after prematching filter redirect from
+ * {@link MyTest#locationWithChangedBaseUri()}.
+ *
+ * @return {@code 201 Created} response with location resolved against new baseUri.
+ */
+ @GET
+ @Path("newUri")
+ public Response redirectedUri() {
+ return Response.created(URI.create("newRedirected")).build();
+ }
+
+ }
+
+
+ /**
+ * Test the URI created in the post-matching request filter.
+ */
+ @Test
+ public void testAbortFilter() {
+ checkResponseFilter("ResponseTest/locationAborted", "uriAfterAbortion/SUCCESS");
+ }
+
+ /**
+ * Test the URI created in the pre-matching request filter.
+ */
+ @Test
+ public void testAbortPreMatchingFilter() {
+ checkResource("ResponseTest/locationAbortedPreMatching", "uriAfterPreMatchingAbortion/SUCCESS");
+ }
+
+
+ /**
+ * Test with URI Rewritten in the container response filter;
+ * Filters do have access to the response headers and can manipulate the location uri so that it contains a relative address.
+ * This test incorporates a filter which replaces the uri with a relative one. However we expect to have absolute uri at
+ * the end of the chain.
+ */
+ @Test
+ public void testAbsoluteUriWithFilter() {
+ checkResource("ResponseTest/locationTestWithFilter", "ResponseTest/UriChangedByFilter");
+ }
+
+ /**
+ * Test with URI Rewritten in the writer interceptor;
+ * Interceptors do have access to the response headers and can manipulate the location uri so that it contains a relative
+ * address.
+ * This test incorporates an interceptor which replaces the uri with a relative one. However we expect to have absolute uri
+ * at the end of the chain.
+ */
+ @Test
+ public void testAbsoluteUriWithInterceptor() {
+ checkResource("ResponseTest/locationWithInterceptor", "ResponseTest/UriChangedByInterceptor");
+ }
+
+
+ /**
+ * Test, that uri is correct in the response filter when created in the exception mapper (synchronous).
+ */
+ @Test
+ public void testExceptionMapperSync() {
+ checkResponseFilter("ResponseTest/exceptionMapperSync", "EXCEPTION_MAPPER");
+ }
+
+ /**
+ * Test, that uri is correct in the response filter when created in the exception mapper (asynchronous).
+ */
+ @Test
+ public void testExceptionMapperAsync() {
+ checkResponseFilter("ResponseTest/exceptionMapperAsync", "EXCEPTION_MAPPER");
+ }
+
+ /**
+ * Test, that uri is correct in the response filter when created in the exception mapper (asynchronous/executor).
+ */
+ @Test
+ public void testExceptionMapperExecutor() {
+ checkResponseFilter("ResponseTest/exceptionMapperExecutor", "EXCEPTION_MAPPER");
+ }
+
+ /**
+ * Test the baseUri and requestUri change in the prematching filter.
+ */
+ @Test
+ public void testLocationBaseUriChangedByPrematchingFilter() {
+ final Response response = target().path("ResponseTest/filterChangedBaseUri").request().get();
+ assertEquals("http://www.server.com/newRedirected", response.getHeaderString("Location"));
+ }
+
+ /**
+ * Test, that uri is correct in the response filter (synchronous).
+ */
+ @Test
+ public void testResponseFilterSync() {
+ checkResponseFilter("ResponseTest/responseFilterSync", "responseFilterSync");
+ }
+
+ /**
+ * Test, that uri is correct in the response filter (asynchronous).
+ */
+ @Test
+ public void testResponseFilterAsync() {
+ checkResponseFilter("ResponseTest/responseFilterAsync", "responseFilterAsync");
+ }
+
+
+
+ /**
+ * Test, that uri is correct in the response filter (asynchronous/executor).
+ */
+ @Test
+ public void testResponseFilterAsyncExecutor() {
+ checkResponseFilter("ResponseTest/responseFilterAsyncExecutor", "responseFilterAsyncExecutor");
+ }
+
+
+
+ /**
+ * Response filter - replaces the Location header with a relative uri.
+ */
+ public static class LocationManipulationFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
+ throws IOException {
+ final MultivaluedMap<String, ?> headers = responseContext.getHeaders();
+ final List<URI> locations = (List<URI>) headers.get(HttpHeaders.LOCATION);
+ locations.set(0, URI.create("ResponseTest/UriChangedByFilter"));
+ LOGGER.info("LocationManipulationFilter applied.");
+ }
+ }
+
+ /**
+ * Response filter - check if the URI is absolute. If it is not correctly absolutized,
+ * it changes the response to 500 - Internal Server Error and sets the error message into the response body.
+ */
+ public static class UriCheckingResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
+ throws IOException {
+ final URI location = responseContext.getLocation();
+ if (!location.isAbsolute()) {
+ responseContext.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ responseContext.setEntity("Response location was not absolute in UriCheckingFilter. Location value: " + location);
+ }
+ }
+ }
+
+ /**
+ * Request Filter which aborts the current request calling ContainerRequestContext.abortWith().
+ *
+ * The returned response is passed to Response.created() and immediately tested for absolutization.
+ * This is necessary, as the relative URI would be absolutized later anyway and would reach the calling test method as
+ * an absolute URI and there would be no way to determine where the URI conversion was done.
+ *
+ * The result of the test is propagated back to the test method by separate URI values in case of a success or a failure.
+ */
+ public static class AbortingRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ LOGGER.info("Aborting request in the request filter. Returning status created.");
+ final String successRelativeUri = "uriAfterAbortion/SUCCESS";
+ Response response = Response.created(URI.create(successRelativeUri)).build();
+
+ if (!response.getLocation().toString().equals(requestContext.getUriInfo().getBaseUri() + successRelativeUri)) {
+ response = Response.created(URI.create("uriAfterAbortion/FAILURE")).build();
+ }
+ requestContext.abortWith(response);
+ }
+ }
+
+ /**
+ * Request Filter which aborts the current request calling ContainerRequestContext.abortWith().
+ *
+ * The returned response is passed to Response.created() and immediately tested for absolutization.
+ * This is necessary, as the relative URI would be absolutized later anyway and would reach the calling test method as
+ * an absolute URI and there would be no way to determine where the URI conversion was done.
+ *
+ * The result of the test is propagated back to the test method by separate URI values in case of a success or a failure.
+ */
+ @PreMatching
+ public static class AbortingPreMatchingRequestFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+
+ if (requestContext.getUriInfo().getAbsolutePath().toString().endsWith("locationAbortedPreMatching")) {
+ LOGGER.info("Aborting request in the request filter. Returning status created.");
+ final String successRelativeUri = "uriAfterPreMatchingAbortion/SUCCESS";
+ Response response = Response.created(URI.create(successRelativeUri)).build();
+ if (!response.getLocation().toString().equals(requestContext.getUriInfo().getBaseUri() + successRelativeUri)) {
+ response = Response.created(URI.create("uriAfterPreMatchingAbortion/FAILURE")).build();
+ }
+ requestContext.abortWith(response);
+ }
+ }
+ }
+
+ /**
+ * Request prematching filter which changes request URI and base URI.
+ *
+ * As a result, different resource mathod should be matched and invoked and return location resolved against the new
+ * base URI.
+ */
+ @PreMatching
+ public static class BaseUriChangingPreMatchingFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.getUriInfo().getAbsolutePath().toString().endsWith("filterChangedBaseUri")) {
+ final URI requestUri = requestContext.getUriInfo().getRequestUri();
+ // NOTE, that the trailing slash matters, without it, the URI is nod valid and is not correctly resolved by the
+ // URI.resolve() method.
+ final URI baseUri = URI.create("http://www.server.com/");
+ requestContext.setRequestUri(baseUri, requestUri.resolve("newUri"));
+ }
+ }
+ }
+
+ /**
+ * Writer interceptor - replaces the Location header with a relative uri.
+ */
+ public static class LocationManipulationInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final MultivaluedMap<String, ?> headers = context.getHeaders();
+ final List<URI> locations = (List<URI>) headers.get(HttpHeaders.LOCATION);
+ locations.set(0, URI.create("ResponseTest/UriChangedByInterceptor"));
+ LOGGER.info("LocationManipulationInterceptor applied.");
+ context.proceed();
+ }
+ }
+
+ /**
+ * Exception mapper which creates a test response with a relative URI.
+ */
+ public static class TestExceptionMapper implements ExceptionMapper<WebApplicationException> {
+
+ @Override
+ public Response toResponse(final WebApplicationException exception) {
+ exception.printStackTrace();
+ return Response.created(URI.create("EXCEPTION_MAPPER")).build();
+ }
+ }
+
+ /**
+ * Registers the filter and interceptor and binds it to the resource methods of interest.
+ */
+ public static class LocationManipulationDynamicBinding implements DynamicFeature {
+
+ @Override
+ public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
+ if (MyTest.class.equals(resourceInfo.getResourceClass())) {
+ final String methodName = resourceInfo.getResourceMethod().getName();
+ if (methodName.contains("locationTestWithFilter")) {
+ context.register(LocationManipulationFilter.class);
+ LOGGER.info("LocationManipulationFilter registered.");
+ }
+ if (methodName.contains("locationTestWithInterceptor")) {
+ context.register(LocationManipulationInterceptor.class);
+ LOGGER.info("LocationManipulationInterceptor registered.");
+ }
+ if (methodName.contains("locationTestAborted")) {
+ context.register(AbortingRequestFilter.class);
+ LOGGER.info("AbortingRequestFilter registered.");
+ }
+ if (methodName.contains("responseFilterSync")
+ || methodName.contains("responseFilterAsync")
+ || methodName.contains("locationTestAborted")
+ || methodName.contains("exceptionMapperSync")
+ || methodName.contains("exceptionMapperAsync")
+ || methodName.contains("exceptionMapperExecutor")) {
+ context.register(UriCheckingResponseFilter.class);
+ LOGGER.info("UriCheckingResponseFilter registered.");
+ }
+ if (methodName.contains("locationWithChangedBaseUri")) {
+ context.register(BaseUriChangingPreMatchingFilter.class);
+ LOGGER.info("BaseUriChangingPreMatchingFilter registered.");
+ }
+ }
+ }
+ }
+
+ private Response checkResource(final String resourcePath, final String expectedRelativeUri) {
+ final Response response = target().path(resourcePath).request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals(getBaseUri() + expectedRelativeUri, location);
+ return response;
+ }
+
+ private void checkResponseFilter(final String resourcePath, final String expectedRelativeUri) {
+ final Response response = target().path(resourcePath).request().get(Response.class);
+ assertNotEquals("Message from response filter: " + response.readEntity(String.class),
+ response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ assertEquals(getBaseUri() + expectedRelativeUri, response.getLocation().toString());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithAbsolutizationDisabledTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithAbsolutizationDisabledTest.java
new file mode 100644
index 0000000..5fd809b
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithAbsolutizationDisabledTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.net.URI;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Test if the location response header is left intact in case the
+ * {@link ServerProperties#LOCATION_HEADER_RELATIVE_URI_RESOLUTION_DISABLED} property is set to {@code true}.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class LocationHeaderWithAbsolutizationDisabledTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(LocationHeaderWithAbsolutizationDisabledTest.class.getName());
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ final ResourceConfig rc = new ResourceConfig(ResponseTest.class);
+ rc.property(ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_DISABLED, Boolean.TRUE);
+ return rc;
+ }
+
+ /**
+ * Test JAX-RS resource
+ */
+ @Path(value = "test")
+ public static class ResponseTest {
+
+ /**
+ * Resource method for the basic uri test
+ * @return test response with relative location uri
+ */
+ @GET
+ @Path("location")
+ public Response locationTest() {
+ final URI uri = URI.create("location");
+ LOGGER.info("URI Created in the resource method > " + uri);
+ return Response.created(uri).build();
+ }
+
+ /**
+ * Resource method for the test with null location
+ * @return test response with null location uri
+ */
+ @GET
+ @Path("locationNull")
+ public Response locationTestNull() {
+ return Response.created(null).build();
+ }
+
+ /**
+ * Resource method for the test with location starting with single slash
+ * @return test response with relative location uri starting with slash
+ */
+ @GET
+ @Path("locationSlash")
+ public Response locationTestSlash() {
+ return Response.created(URI.create("/location")).build();
+ }
+ }
+
+ /**
+ * Test with relative location;
+ * Ensures, that the location remains intact
+ */
+ @Test
+ public void testLocation() {
+ final Response response = target().path("test/location").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals("location", location);
+ }
+
+ /**
+ * Test with relative location with leading slash
+ */
+ @Test
+ public void testLocationWithSlash() {
+ final Response response = target().path("test/locationSlash").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals("/location", location);
+ }
+
+ /**
+ * Test with relative location with leading slash
+ */
+ @Test
+ public void testNullLocation() {
+ final Response response = target().path("test/locationNull").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertNull(location);
+ }
+}
+
+
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithIncompatibleFlagTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithIncompatibleFlagTest.java
new file mode 100644
index 0000000..89b6e5c
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/LocationHeaderWithIncompatibleFlagTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.net.URI;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Test if the location response header is resolved according to RFC7231 (in a JAX-RS 2.0 incompatible way) when
+ * {@link ServerProperties#LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231} property is set to {@code true} and
+ * {@link ServerProperties#LOCATION_HEADER_RELATIVE_URI_RESOLUTION_DISABLED} to {@code false}
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class LocationHeaderWithIncompatibleFlagTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(LocationHeaderWithIncompatibleFlagTest.class.getName());
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ final ResourceConfig rc = new ResourceConfig(ResponseTest.class);
+ rc.property(ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231, Boolean.TRUE);
+ return rc;
+ }
+
+ /**
+ * Test JAX-RS resource
+ */
+ @Path(value = "test")
+ public static class ResponseTest {
+ /**
+ * Resource method for the basic uri test
+ * @return test response with relative location uri
+ */
+ @GET
+ @Path("location")
+ public Response locationTest() {
+ final URI uri = URI.create("location");
+ return Response.created(uri).build();
+ }
+
+ /**
+ * Resource method for the test with null location
+ * @return test response with null location uri
+ */
+ @GET
+ @Path("locationNull")
+ public Response locationTestNull() {
+ return Response.created(null).build();
+ }
+
+ /**
+ * Resource method for the test with location starting with single slash
+ * @return test response with relative location uri starting with slash
+ */
+ @GET
+ @Path("locationSlash")
+ public Response locationTestSlash() {
+ return Response.created(URI.create("/location")).build();
+ }
+ }
+
+ /**
+ * Test with relative location;
+ * Ensures, that the location remains intact
+ */
+ @Test
+ public void testLocation() {
+ final Response response = target().path("test/location").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals(getBaseUri().toString() + "test/location", location);
+ }
+
+ /**
+ * Test with relative location with leading slash
+ */
+ @Test
+ public void testLocationWithSlash() {
+ final Response response = target().path("test/locationSlash").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertEquals(getBaseUri() + "location", location);
+ }
+
+ /**
+ * Test with relative location with leading slash
+ */
+ @Test
+ public void testNullLocation() {
+ final Response response = target().path("test/locationNull").request(MediaType.TEXT_PLAIN).get(Response.class);
+ final String location = response.getHeaderString(HttpHeaders.LOCATION);
+ LOGGER.info("Location resolved from response > " + location);
+ assertNull(location);
+ }
+}
+
+
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MediaTypeProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MediaTypeProviderTest.java
new file mode 100644
index 0000000..99147b2
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MediaTypeProviderTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.HashMap;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.MediaTypeProvider;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Media type provider tests.
+ *
+ * @author Mark Hadley
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MediaTypeProviderTest {
+ @Test
+ public void testToString() {
+ final MediaType header = new MediaType("application", "xml");
+ final MediaTypeProvider instance = new MediaTypeProvider();
+
+ final String expResult = "application/xml";
+ final String result = instance.toString(header);
+ assertEquals(expResult, result);
+ }
+
+ @Test
+ public void testToStringWithParams() {
+ final HashMap<String, String> params = new HashMap<>();
+ params.put("charset", "utf8");
+ final MediaType header = new MediaType("application", "xml", params);
+ final MediaTypeProvider instance = new MediaTypeProvider();
+
+ final String expResult = "application/xml;charset=utf8";
+ final String result = instance.toString(header);
+ assertEquals(expResult, result);
+ }
+
+ @Test
+ public void testFromString() throws Exception {
+ final MediaTypeProvider instance = new MediaTypeProvider();
+
+ final String header = "application/xml";
+ final MediaType result = instance.fromString(header);
+ assertEquals(result.getType(), "application");
+ assertEquals(result.getSubtype(), "xml");
+ assertEquals(result.getParameters().size(), 0);
+ }
+
+ @Test
+ public void testFromStringWithParams() throws Exception {
+ final String header = "application/xml;charset=utf8";
+ final MediaTypeProvider instance = new MediaTypeProvider();
+
+ final MediaType result = instance.fromString(header);
+ assertEquals(result.getType(), "application");
+ assertEquals(result.getSubtype(), "xml");
+ assertEquals(result.getParameters().size(), 1);
+ assertTrue(result.getParameters().containsKey("charset"));
+ assertEquals(result.getParameters().get("charset"), "utf8");
+ }
+
+ @Test
+ public void testWithQuotedParam() {
+ final HashMap<String, String> params = new HashMap<String, String>();
+ params.put("foo", "\"bar\"");
+ final MediaType header = new MediaType("application", "xml", params);
+ final MediaTypeProvider instance = new MediaTypeProvider();
+
+ final String result = instance.toString(header);
+ final String expResult = "application/xml;foo=\"\\\"bar\\\"\"";
+ assertEquals(expResult, result);
+
+ final MediaType m = instance.fromString(result);
+ assertEquals("\"bar\"", m.getParameters().get("foo"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyReaderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyReaderTest.java
new file mode 100644
index 0000000..d0bd7f6
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyReaderTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Jan Supol (jan.supol at oracle.com)
+ * @author Michal Gajdos
+ */
+public class MessageBodyReaderTest extends JerseyTest {
+
+ @Path("resource")
+ public static class Resource {
+
+ @Context
+ private HttpHeaders headers;
+
+ @POST
+ @Path("plain")
+ public String plain(final EntityForReader entity) {
+ return entity.getValue() + ";" + headers.getHeaderString(HttpHeaders.CONTENT_TYPE);
+ }
+ }
+
+ @Provider
+ @Consumes(MediaType.APPLICATION_OCTET_STREAM)
+ public static class AppOctetReader implements MessageBodyReader<EntityForReader> {
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return MediaType.APPLICATION_OCTET_STREAM_TYPE.equals(mediaType);
+ }
+
+ @Override
+ public EntityForReader readFrom(final Class<EntityForReader> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ // Underlying stream should not be closed and Jersey is preventing from closing it.
+ entityStream.close();
+
+ return new EntityForReader(ReaderWriter.readFromAsString(entityStream, mediaType));
+ }
+ }
+
+ public static class EntityForReader {
+
+ private String value;
+
+ public EntityForReader(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class).register(LoggingFeature.class).register(AppOctetReader.class);
+ }
+
+ /**
+ * Test whether the default {@link MediaType} ({@value MediaType#APPLICATION_OCTET_STREAM}) is passed to a reader if no
+ * {@value HttpHeaders#CONTENT_TYPE} value is provided in a request.
+ */
+ @Test
+ public void testDefaultContentTypeForReader() throws Exception {
+ final HttpPost httpPost = new HttpPost(UriBuilder.fromUri(getBaseUri()).path("resource/plain").build());
+ httpPost.setEntity(new ByteArrayEntity("value".getBytes()));
+ httpPost.removeHeaders("Content-Type");
+
+ final HttpClient httpClient = HttpClientBuilder.create().build();
+ final HttpResponse response = httpClient.execute(httpPost);
+
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals("value;null", ReaderWriter.readFromAsString(response.getEntity().getContent(), null));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java
new file mode 100644
index 0000000..c9f051f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.ServerErrorException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Various MessageBodyWriter tests.
+ *
+ * @author Michal Gajdos
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class MessageBodyWriterTest extends JerseyTest {
+
+ private static final String HEADER_NAME = "MessageBodyWriterTestHeader";
+ private static final String HEADER_VALUE_CLIENT = "Client";
+ private static final String HEADER_VALUE_SERVER = "Server";
+
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, OverridingStringProvider.class, HtmlStringProvider.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(OverridingStringProvider.class);
+ }
+
+ @Provider
+ @Produces("text/plain")
+ public static class OverridingStringProvider implements MessageBodyWriter<String> {
+
+ @Context
+ private Configuration config;
+
+ @Override
+ public boolean isWriteable(
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(
+ final String t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(
+ final String t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ // Underlying stream should not be closed and Jersey is preventing from closing it.
+ entityStream.close();
+
+ httpHeaders.putSingle(HEADER_NAME,
+ config.getRuntimeType() == RuntimeType.SERVER ? HEADER_VALUE_SERVER : HEADER_VALUE_CLIENT);
+
+ entityStream.write(t.getBytes());
+ }
+ }
+
+ @Provider
+ @Produces("text/html")
+ public static class HtmlStringProvider implements MessageBodyWriter<String> {
+
+ @Context
+ private Configuration config;
+
+ @Override
+ public boolean isWriteable(
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+
+ if (MediaTypes.typeEqual(MediaType.TEXT_HTML_TYPE, mediaType)) {
+ final String charset = mediaType.getParameters().get("charset");
+ if (charset == null || !"utf-8".equalsIgnoreCase(charset)) {
+ throw new ServerErrorException("Charset not received in isWritable()", 501);
+ }
+ }
+
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(
+ final String t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(
+ final String entity,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+
+ final String charset = mediaType.getParameters().get("charset");
+ if (charset == null || !"utf-8".equalsIgnoreCase(charset)) {
+ throw new ServerErrorException("Charset not received in writeTo()", 502);
+ }
+
+ String html = "<html><body>" + entity + "</body></html>";
+ entityStream.write(html.getBytes());
+ }
+ }
+
+ /**
+ * Test resource.
+ */
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ public String post(@HeaderParam(HEADER_NAME) final String header, final String post) {
+ assertEquals(HEADER_VALUE_CLIENT, header);
+ return post;
+ }
+
+ @GET
+ @Produces("text/html;charset=utf-8")
+ @Path("html-charset-in-produces")
+ public String getHtmlForCharsetInProduces() {
+ return "foo";
+ }
+
+ @GET
+ @Path("html-charset-explicit-in-response")
+ public Response getHtmlForExplicitCharsetInResponse() {
+ return Response.ok("foo", MediaType.TEXT_HTML_TYPE.withCharset("utf-8")).build();
+ }
+
+ @GET
+ @Produces("text/html")
+ @Path("html-charset-in-accepts")
+ public String getHtmlForCharsetInAccepts() {
+ return "foo";
+ }
+
+ }
+
+ /**
+ * Test that it's possible to override default MessageBodyWriter instances.
+ */
+ @Test
+ public void testOverride() {
+ final Response response = target().request("text/plain").post(Entity.text("content"));
+
+ assertEquals("content", response.readEntity(String.class));
+ assertEquals(HEADER_VALUE_SERVER, response.getHeaderString(HEADER_NAME));
+ }
+
+ /**
+ * Test that media type parameters specified in @Produces or explicitly in a server response are received
+ * in the selected message body writer.
+ */
+ @Test
+ public void testMediaTypeParametersInMessageBodyWriter() {
+ Response response;
+
+ response = target().path("html-charset-in-produces").request("text/html").get();
+ assertThat("MediaType charset parameter in @Produces failed to propagate into MessageBodyWriter",
+ response.getStatus(), equalTo(200));
+ assertThat("Unexpected response content returned from server.",
+ response.readEntity(String.class), equalTo("<html><body>foo</body></html>"));
+
+ response = target().path("html-charset-explicit-in-response").request("text/html").get();
+ assertThat("MediaType charset parameter explicitly set in Response failed to propagate into MessageBodyWriter",
+ response.getStatus(), equalTo(200));
+ assertThat("Unexpected response content returned from server.",
+ response.readEntity(String.class), equalTo("<html><body>foo</body></html>"));
+
+ response = target().path("html-charset-in-accepts").request(MediaType.TEXT_HTML_TYPE.withCharset("utf-8")).get();
+ assertThat("MediaType charset parameter sent with request in Accept header failed to propagate into MessageBodyWriter",
+ response.getStatus(), equalTo(200));
+ assertThat("Unexpected response content returned from server.",
+ response.readEntity(String.class), equalTo("<html><body>foo</body></html>"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/OptionsTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/OptionsTest.java
new file mode 100644
index 0000000..dcc1a01
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/OptionsTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class OptionsTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HttpOptionsTest.class);
+ }
+
+ @Path("/OptionsTest")
+ public static class HttpOptionsTest {
+
+ static String html_content =
+ "<html><head><title>get text/html</title></head>"
+ + "<body>get text/html</body></html>";
+
+ @GET
+ public Response getPlain() {
+ return Response.ok("CTS-get text/plain").header("TEST-HEAD", "text-plain")
+ .build();
+ }
+
+ @GET
+ @Produces("text/html")
+ public Response getHtml() {
+ return Response.ok(html_content).header("TEST-HEAD", "text-html")
+ .build();
+ }
+
+ @GET
+ @Path("/sub")
+ public Response getSub() {
+ return Response.ok("TEST-get text/plain").header("TEST-HEAD",
+ "sub-text-plain")
+ .build();
+ }
+
+ @GET
+ @Path("/sub")
+ @Produces(value = "text/html")
+ public Response headSub() {
+ return Response.ok(html_content).header("TEST-HEAD", "sub-text-html")
+ .build();
+ }
+ }
+
+ /*
+ * Client invokes OPTIONS on a sub resource at /OptionsTest/sub;
+ * which no request method designated for OPTIONS.
+ * Verify that an automatic response is generated.
+ */
+ @Test
+ public void OptionSubTest() {
+ final Response response = target().path("/OptionsTest/sub").request(MediaType.TEXT_HTML_TYPE).options();
+
+ assertTrue(response.getAllowedMethods().contains("GET"));
+ assertTrue(response.getAllowedMethods().contains("HEAD"));
+ assertTrue(response.getAllowedMethods().contains("OPTIONS"));
+
+ assertEquals(response.getMediaType(), MediaType.TEXT_HTML_TYPE);
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/QualitySourceMediaTypeProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/QualitySourceMediaTypeProviderTest.java
new file mode 100644
index 0000000..8371909
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/QualitySourceMediaTypeProviderTest.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.HttpHeaderReader;
+import org.glassfish.jersey.message.internal.QualitySourceMediaType;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author unknown
+ */
+public class QualitySourceMediaTypeProviderTest {
+
+ @Test
+ public void testOneMediaType() throws Exception {
+ final String header = "application/xml";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+ assertEquals(1, l.size());
+ final MediaType m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testOneMediaTypeWithParameters() throws Exception {
+ final String header = "application/xml;charset=utf8";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(1, l.size());
+
+ final MediaType m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ assertTrue(m.getParameters().containsKey("charset"));
+ assertEquals("utf8", m.getParameters().get("charset"));
+ }
+
+ @Test
+ public void testMultipleMediaType() throws Exception {
+ final String header = "application/xml, text/xml, text/html";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMultipleMediaTypeWithQuality() throws Exception {
+ final String header = "application/xml;qs=0.1, text/xml;qs=0.2, text/html;qs=0.3";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testMultipleMediaTypeWithQuality2() throws Exception {
+ final String header = "application/xml;qs=0.1, text/xml;qs=0.2, text/html;qs=0.93";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testHttpURLConnectionAcceptHeader() throws Exception {
+ final String header = "text/html, image/gif, image/jpeg, */*; qs=.2";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(4, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("image", m.getType());
+ assertEquals("gif", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("image", m.getType());
+ assertEquals("jpeg", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testFirefoxAcceptHeader() throws Exception {
+ final String header = "text/xml,application/xml,application/xhtml+xml,text/html;qs=0.9,text/plain;qs=0.8,image/png,*/*;"
+ + "qs=0.5";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(7, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("application", m.getType());
+ assertEquals("xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("application", m.getType());
+ assertEquals("xhtml+xml", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("image", m.getType());
+ assertEquals("png", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(6);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifity() throws Exception {
+ final String header = "*/*, text/*, text/plain";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(3, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityWithQuality() throws Exception {
+ final String header = "*/*, */*;qs=0.5, text/*, text/*;qs=0.5, text/plain, text/plain;qs=0.5";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ assertEquals(6, l.size());
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("text", m.getType());
+ assertEquals("plain", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(4);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(5);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityHTTPExample1() throws Exception {
+ final String header = "text/*, text/html, text/html;level=1, */*";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+
+ @Test
+ public void testMediaTypeSpecifityHTTPExample2() throws Exception {
+ final String header = "text/*, text/html;level=1, text/html, */*";
+ final List<QualitySourceMediaType> l = HttpHeaderReader.readQualitySourceMediaType(header);
+
+ MediaType m;
+ m = l.get(0);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(1, m.getParameters().size());
+ m = l.get(1);
+ assertEquals("text", m.getType());
+ assertEquals("html", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(2);
+ assertEquals("text", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ m = l.get(3);
+ assertEquals("*", m.getType());
+ assertEquals("*", m.getSubtype());
+ assertEquals(0, m.getParameters().size());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResourceContextTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResourceContextTest.java
new file mode 100644
index 0000000..2d2acdc
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResourceContextTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test {@link ResourceContext}: resource context must provide access to
+ * sub-resources that can be provided by a custom component provider.
+ *
+ * @author Martin Grotzke
+ * @author Paul Sandoz
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ * @author Miroslav Fuksa
+ */
+public class ResourceContextTest extends JerseyTest {
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyRootResource.class);
+ }
+
+ @Path("/")
+ public static class MyRootResource {
+
+ @Context
+ ResourceContext resourceContext;
+
+ @Path("singleton")
+ public SingletonResource getSingletonResource() {
+ return resourceContext.getResource(SingletonResource.class);
+ }
+
+ @Path("perrequest")
+ public PerRequestResource getPerRequestSubResource() {
+ return resourceContext.getResource(PerRequestResource.class);
+ }
+
+ @Path("inject/{path}")
+ public InjectResource getInjectResource() {
+ final InjectResource resource = resourceContext.getResource(InjectResource.class);
+ resource.setPath("something");
+ return resourceContext.initResource(resource);
+ }
+
+ @Path("injectFromNewResource/{path}")
+ public InjectResource getInjectResourceFromNew() {
+ final InjectResource resource = new InjectResource();
+ resource.setPath("something");
+ return resourceContext.initResource(resource);
+ }
+
+ }
+
+ public static class InjectResource {
+ @PathParam("path")
+ private String path;
+
+ @GET
+ public String get() {
+ return path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+ }
+
+
+ @Singleton
+ public static class SingletonResource {
+ int i;
+
+ @GET
+ public String get() {
+ i++;
+ return Integer.toString(i);
+ }
+ }
+
+ public static class PerRequestResource {
+ int i;
+
+ @GET
+ public String get() {
+ i++;
+ return Integer.toString(i);
+ }
+ }
+
+ @Test
+ public void testGetResourceFromResourceContext() {
+ assertEquals("1", target("/singleton").request().get(String.class));
+ assertEquals("2", target("/singleton").request().get(String.class));
+
+ assertEquals("1", target("/perrequest").request().get(String.class));
+ assertEquals("1", target("/perrequest").request().get(String.class));
+ }
+
+
+ @Test
+ public void testInitializeResourceFromResourceContext() {
+ assertEquals("aaa", target("/inject/aaa").request().get(String.class));
+ assertEquals("bbb", target("/inject/bbb").request().get(String.class));
+ }
+
+ @Test
+ public void testInitializeResourceFromNewResource() {
+ assertEquals("aaa", target("/injectFromNewResource/aaa").request().get(String.class));
+ assertEquals("bbb", target("/injectFromNewResource/bbb").request().get(String.class));
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseE2ETest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseE2ETest.java
new file mode 100644
index 0000000..b206551
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseE2ETest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Response E2E tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ResponseE2ETest extends JerseyTest {
+
+ /**
+ * Custom OK response.
+ */
+ public static class OkResponse extends Response {
+
+ private Response r;
+
+ /**
+ * Custom OK response constructor.
+ *
+ * @param entity entity content.
+ */
+ public OkResponse(String entity) {
+ r = Response.ok(entity).build();
+ }
+
+ @Override
+ public int getStatus() {
+ return r.getStatus();
+ }
+
+ @Override
+ public StatusType getStatusInfo() {
+ return r.getStatusInfo();
+ }
+
+ @Override
+ public Object getEntity() {
+ return r.getEntity();
+ }
+
+ @Override
+ public <T> T readEntity(Class<T> entityType) {
+ return r.readEntity(entityType);
+ }
+
+ @Override
+ public <T> T readEntity(GenericType<T> entityType) {
+ return r.readEntity(entityType);
+ }
+
+ @Override
+ public <T> T readEntity(Class<T> entityType, Annotation[] annotations) {
+ return r.readEntity(entityType, annotations);
+ }
+
+ @Override
+ public <T> T readEntity(GenericType<T> entityType, Annotation[] annotations) {
+ return r.readEntity(entityType, annotations);
+ }
+
+ @Override
+ public boolean hasEntity() {
+ return r.hasEntity();
+ }
+
+ @Override
+ public boolean bufferEntity() {
+ return r.bufferEntity();
+ }
+
+ @Override
+ public void close() {
+ r.close();
+ }
+
+ @Override
+ public MediaType getMediaType() {
+ return r.getMediaType();
+ }
+
+ @Override
+ public Locale getLanguage() {
+ return r.getLanguage();
+ }
+
+ @Override
+ public int getLength() {
+ return r.getLength();
+ }
+
+ @Override
+ public Set<String> getAllowedMethods() {
+ return r.getAllowedMethods();
+ }
+
+ @Override
+ public Map<String, NewCookie> getCookies() {
+ return r.getCookies();
+ }
+
+ @Override
+ public EntityTag getEntityTag() {
+ return r.getEntityTag();
+ }
+
+ @Override
+ public Date getDate() {
+ return r.getDate();
+ }
+
+ @Override
+ public Date getLastModified() {
+ return r.getLastModified();
+ }
+
+ @Override
+ public URI getLocation() {
+ return r.getLocation();
+ }
+
+ @Override
+ public Set<Link> getLinks() {
+ return r.getLinks();
+ }
+
+ @Override
+ public boolean hasLink(String relation) {
+ return r.hasLink(relation);
+ }
+
+ @Override
+ public Link getLink(String relation) {
+ return r.getLink(relation);
+ }
+
+ @Override
+ public Link.Builder getLinkBuilder(String relation) {
+ return r.getLinkBuilder(relation);
+ }
+
+ @Override
+ public MultivaluedMap<String, Object> getMetadata() {
+ return r.getMetadata();
+ }
+
+ @Override
+ public MultivaluedMap<String, Object> getHeaders() {
+ return r.getHeaders();
+ }
+
+ @Override
+ public MultivaluedMap<String, String> getStringHeaders() {
+ return r.getStringHeaders();
+ }
+
+ @Override
+ public String getHeaderString(String name) {
+ return r.getHeaderString(name);
+ }
+ }
+
+ @Path("response")
+ public static class ResponseTestResource {
+
+ @GET
+ @Path("custom")
+ public OkResponse subresponse() {
+ return new OkResponse("subresponse");
+ }
+
+ @GET
+ @Path("null")
+ public Response nullResponse() {
+ return null;
+ }
+
+ @GET
+ @Path("no-status-with-entity")
+ public Response entityResponseTest() {
+ return RuntimeDelegate.getInstance().createResponseBuilder().entity("1234567890").build();
+ }
+
+ @GET
+ @Path("no-status-without-entity")
+ public Response noEntityResponseTest() {
+ return RuntimeDelegate.getInstance().createResponseBuilder().build();
+ }
+
+ @Uri("response/internal")
+ WebTarget target;
+
+ @GET
+ @Path("external")
+ public Response external() {
+ Response response;
+ if (target == null) {
+ response = Response.serverError().entity("injected WebTarget is null").build();
+ } else {
+ response = target.request().buildGet().invoke();
+ }
+ return response;
+ }
+
+ @GET
+ @Path("internal")
+ public String internal() {
+ return "internal";
+ }
+
+ @PUT
+ @Path("not-modified-put")
+ public Response notModifiedPut(String data) {
+ return Response.notModified().entity("not-modified-" + data).build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResponseTestResource.class);
+ }
+
+ /**
+ * JERSEY-1516 reproducer.
+ */
+ @Test
+ public void testCustomResponse() {
+ final Response response = target("response").path("custom").request().get();
+
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertEquals("Unexpected response entity.", "subresponse", response.readEntity(String.class));
+ }
+
+ /**
+ * JERSEY-1527 reproducer.
+ */
+ @Test
+ public void testNoStatusResponse() {
+ final WebTarget target = target("response").path("no-status-{param}-entity");
+ Response response;
+
+ response = target.resolveTemplate("param", "with").request().get();
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertEquals("Unexpected response entity.", "1234567890", response.readEntity(String.class));
+
+ response = target.resolveTemplate("param", "without").request().get();
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 204, response.getStatus());
+ assertFalse("Unexpected non-empty response entity.", response.hasEntity());
+ }
+
+ /**
+ * JERSEY-1528 reproducer.
+ */
+ @Test
+ public void testNullResponse() {
+ final Response response = target("response").path("null").request().get();
+
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 204, response.getStatus());
+ assertFalse("Unexpected non-empty response entity.", response.hasEntity());
+ }
+
+ /**
+ * JERSEY-1531 reproducer.
+ */
+ @Test
+ public void testInboundOutboundResponseMixing() {
+ final WebTarget target = target("response").path("external");
+ Response response;
+
+ response = target.request().get();
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", 200, response.getStatus());
+ assertEquals("Unexpected response entity.", "internal", response.readEntity(String.class));
+ }
+
+ /**
+ * JERSEY-845 reproducer.
+ *
+ * Verifies consistent behavior over time ("works as designed").
+ */
+ @Test
+ public void testEntityInNotModifiedPutResposne() {
+ final WebTarget target = target("response").path("not-modified-put");
+ Response response;
+
+ response = target.request().put(Entity.text("put-data"));
+ assertNotNull("Response is null.", response);
+ assertEquals("Unexpected response status.", Response.Status.NOT_MODIFIED.getStatusCode(), response.getStatus());
+ // response entity is dropped by server container in compliance with HTTP 1.1 spec
+ assertFalse("Unexpected response entity.", response.hasEntity());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseIntegrationTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseIntegrationTest.java
new file mode 100644
index 0000000..dc63ab4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseIntegrationTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ResponseIntegrationTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(ResponseIntegrationTest.ResponseTest.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+ }
+
+ @Path(value = "/ResponseTest")
+ public static class ResponseTest {
+
+ @GET
+ @Produces(value = "text/plain")
+ public Response statusTest(@QueryParam("status") int status) {
+ Response res;
+ Response.ResponseBuilder resp;
+
+ switch (status) {
+ case 200:
+ resp = Response.ok();
+ break;
+ case 204:
+ case 201:
+ case 202:
+ case 303:
+ case 304:
+ case 307:
+ case 400:
+ case 401:
+ case 403:
+ case 404:
+ case 406:
+ case 409:
+ case 410:
+ case 415:
+ case 500:
+ case 503:
+ case 411:
+ case 412:
+ resp = Response.status(status);
+ break;
+ default:
+ resp = Response.ok().entity("Unexpected parameter in request: " + status);
+ break;
+ }
+
+ res = resp.header("TESTHEADER", "status code in request = " + status).build();
+ return res;
+ }
+ }
+
+ private void testStatus(int status) {
+ final Response response = target().path("ResponseTest").queryParam("status", status).request(MediaType.TEXT_PLAIN)
+ .get(Response.class);
+
+ assertEquals(status, response.getStatus());
+ }
+
+ private void testGenericStatus(int status) {
+ final GenericType<Response> genericType = new GenericType<>(Response.class);
+ final Response response = target().path("ResponseTest").queryParam("status", status).request(MediaType.TEXT_PLAIN)
+ .get(genericType);
+
+ assertEquals(status, response.getStatus());
+ }
+
+ /*
+ * Client send request to a resource,
+ * verify that correct status code returned
+ */
+ @Test
+ public void testStatuses() {
+ final int[] statuses = new int[] {
+ 200,
+ 201,
+ 202,
+ 204,
+ 303,
+ 304,
+ 307,
+ 401,
+ 403,
+ 404,
+ 406,
+ 409,
+ 410,
+ 411,
+ 412,
+ 415,
+ 500,
+ 503
+ };
+
+ for (Integer i : statuses) {
+ System.out.println("### Testing status: " + i);
+ testStatus(i);
+ }
+ }
+
+ /*
+ * Client send request to a resource,
+ * verify that correct status code returned
+ */
+ @Test
+ public void testGenericStatuses() {
+ final int[] statuses = new int[] {
+ 200,
+ 201,
+ 202,
+ 204,
+ 303,
+ 304,
+ 307,
+ 401,
+ 403,
+ 404,
+ 406,
+ 409,
+ 410,
+ 411,
+ 412,
+ 415,
+ 500,
+ 503
+ };
+
+ for (Integer i : statuses) {
+ System.out.println("### Testing status: " + i);
+ testGenericStatus(i);
+ }
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseTest.java
new file mode 100644
index 0000000..be018cc
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ResponseTest.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.security.AccessController;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.message.internal.HeaderUtils;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ResponseTest {
+
+ /*
+ * Create an instance of Response using Response.ok(String, Variant).build()
+ * verify that correct status code is returned
+ */
+ @Test
+ public void OkTest5() {
+ Response resp;
+ int status = 200;
+ String content = "Test Only";
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<String> lang = Arrays.asList("en-US", "en-GB", "zh-CN");
+
+ MediaType mt = new MediaType("text", "plain");
+ List<Variant> vts = Variant.VariantListBuilder.newInstance().mediaTypes(mt)
+ .languages(new Locale("en", "US"), new Locale("en", "GB"),
+ new Locale("zh", "CN")).encodings((String[]) encoding.toArray())
+ .add().build();
+
+ String tmp;
+ for (Variant vt : vts) {
+ resp = Response.ok(content, vt).build();
+ tmp = verifyResponse(resp, content, status, encoding, lang, null,
+ null, null, null);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + tmp);
+ fail();
+ }
+ }
+ }
+
+ /*
+ * Create an instance of Response using
+ * Response.ResponseBuilder.clone()
+ * verify that correct status code is returned
+ */
+ @Test
+ public void cloneTest() throws CloneNotSupportedException {
+ StringBuilder sb = new StringBuilder();
+
+ int status = 200;
+ List<String> type = Arrays.asList("text/plain", "text/html");
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<String> lang = Arrays.asList("en-US", "en-GB", "zh-CN");
+
+ String name = "name_1";
+ String value = "value_1";
+ Cookie ck1 = new Cookie(name, value);
+ NewCookie nck1 = new NewCookie(ck1);
+
+ List<String> cookies = Arrays.asList(nck1.toString().toLowerCase());
+
+ Response.ResponseBuilder respb1 = Response.status(status)
+ .header("Content-type", "text/plain").header("Content-type",
+ "text/html").header("Content-Language", "en-US")
+ .header("Content-Language", "en-GB").header("Content-Language",
+ "zh-CN").header("Cache-Control", "no-transform")
+ .header("Set-Cookie", "name_1=value_1;version=1");
+ Response.ResponseBuilder respb2 = respb1.clone();
+
+ Response resp2 = respb2.build();
+
+ String tmp = verifyResponse(resp2, null, status, encoding, lang, type,
+ null, null, cookies);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + sb.toString());
+ fail();
+ }
+ sb.append(tmp).append(newline);
+
+ String content = "TestOnly";
+ Response resp1 = respb1.entity(content).cookie((NewCookie) null).build();
+ tmp = verifyResponse(resp1, content, status, encoding, lang, type,
+ null, null, null);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + sb.toString());
+ fail();
+ }
+
+ MultivaluedMap<java.lang.String, java.lang.Object> mvp =
+ resp1.getMetadata();
+ if (mvp.containsKey("Set-Cookie")) {
+ sb.append("Response contains unexpected Set-Cookie: ").append(mvp.getFirst("Set-Cookie").toString()).append(newline);
+ System.out.println("### " + sb.toString());
+ fail();
+ }
+ sb.append(tmp).append(newline);
+ }
+
+ /*
+ * Create an instance of Response using
+ * Response.fromResponse(Response).build()
+ * verify that correct status code is returned
+ */
+ @Test
+ public void fromResponseTest() {
+ int status = 200;
+ String content = "Test Only";
+ List<String> type = Arrays.asList("text/plain", "text/html");
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<String> lang = Arrays.asList("en-US", "en-GB", "zh-CN");
+
+ MediaType mt1 = new MediaType("text", "plain");
+ MediaType mt2 = new MediaType("text", "html");
+ List<Variant> vts = Variant.VariantListBuilder.newInstance().mediaTypes(mt1, mt2)
+ .languages(new Locale("en", "US"), new Locale("en", "GB"),
+ new Locale("zh", "CN")).encodings((String[]) encoding.toArray())
+ .add().build();
+
+ String tmp;
+ for (Variant vt : vts) {
+ Response resp1 = Response.ok(content, vt).build();
+ Response resp = Response.fromResponse(resp1).build();
+ tmp = verifyResponse(resp, content, status, encoding, lang, type,
+ null, null, null);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + tmp);
+ fail();
+ }
+ }
+ }
+
+ /*
+ * Create an instance of Response using
+ * Response.ResponseBuilder.header(String, Object).build()
+ * verify that correct status code is returned
+ */
+ @Test
+ public void headerTest() {
+ int status = 200;
+ List<String> type = Arrays.asList("text/plain", "text/html");
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<String> lang = Arrays.asList("en-US", "en-GB", "zh-CN");
+
+ String name = "name_1";
+ String value = "value_1";
+ Cookie ck1 = new Cookie(name, value);
+ NewCookie nck1 = new NewCookie(ck1);
+
+ List<String> cookies = Arrays.asList(nck1.toString().toLowerCase());
+
+ Response resp = Response.status(status).header("Content-type",
+ "text/plain").header("Content-type", "text/html").header("Content-Language", "en-US")
+ .header("Content-Language", "en-GB").header("Content-Language",
+ "zh-CN").header("Cache-Control", "no-transform")
+ .header("Set-Cookie", "name_1=value_1;version=1").build();
+ String tmp = verifyResponse(resp, null, status, encoding, lang, type,
+ null, null, cookies);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + tmp);
+ fail();
+ }
+ }
+
+ /*
+ * Create an instance of Response using
+ * Response.status(int).variant(Variant).build()
+ * verify that correct status code is returned
+ */
+ @Test
+ public void variantTest() {
+ Response resp;
+ int status = 200;
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<String> lang = Arrays.asList("en-US", "en-GB", "zh-CN");
+
+ MediaType mt = new MediaType("text", "plain");
+ List<Variant> vts = Variant.VariantListBuilder.newInstance().mediaTypes(mt)
+ .languages(new Locale("en", "US"), new Locale("en", "GB"),
+ new Locale("zh", "CN")).encodings((String[]) encoding.toArray())
+ .add().build();
+
+ String tmp;
+ for (Variant vt : vts) {
+ resp = Response.status(status).variant(vt).build();
+ tmp = verifyResponse(resp, null, status, encoding, lang, null, null,
+ null, null);
+ if (tmp.endsWith("false")) {
+ System.out.println("### " + tmp);
+ fail();
+ }
+ }
+ }
+
+ private static final String indent = " ";
+ private static final String newline = AccessController.doPrivileged(PropertiesHelper.getSystemProperty("line.separator"));
+
+ private String verifyResponse(Response resp, String content, int status,
+ List<String> encoding, List<String> language, List<String> type,
+ List<String> var, List<String> ccl, List<String> cookies) {
+ boolean pass = true;
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("========== Verifying a Response: ").append(newline);
+
+ String tmp = verifyResponse(resp, content, status, null);
+ sb.append(indent).append(tmp).append(newline);
+ if (tmp.endsWith("false")) {
+ pass = false;
+ }
+
+ MultivaluedMap<String, String> mvp = HeaderUtils.asStringHeaders(
+ resp.getMetadata());
+
+ for (String key : mvp.keySet()) {
+ sb.append(indent + "Processing Key found in response: ").append(key).append(": ").append(mvp.get(key)).append("; ")
+ .append(newline);
+
+ if (key.equalsIgnoreCase("Vary")) {
+ for (String value : var) {
+ String actual = mvp.get(key).toString().toLowerCase();
+ if (!actual.contains(value)) {
+ pass = false;
+ sb.append(indent + indent + "Expected header ").append(value).append(" not set in Vary.").append(newline);
+ } else {
+ sb.append(indent + indent + "Found expected header ").append(value).append(".").append(newline);
+ }
+ }
+ }
+
+ if (encoding != null) {
+ if (key.equalsIgnoreCase("Content-encoding")) {
+ for (Object enc : mvp.get(key)) {
+ if (!encoding.contains(enc.toString().toLowerCase())) {
+ pass = false;
+ sb.append(indent + indent + "Encoding test failed: ").append(newline);
+ }
+ }
+ }
+ }
+
+ if (language != null) {
+ if (key.equalsIgnoreCase("Content-language")) {
+ for (String lang : mvp.get(key)) {
+ if (!language.contains(lang)) {
+ pass = false;
+ sb.append(indent + indent + "language test failed: ").append(lang)
+ .append(" is not expected in Response").append(newline);
+ for (String tt : language) {
+ sb.append(indent + indent + "Expecting Content-Language ").append(tt).append(newline);
+ }
+ }
+ }
+ }
+ }
+
+ if (type != null) {
+ if (key.equalsIgnoreCase("Content-Type")) {
+ for (Object lang : mvp.get(key)) {
+ if (!type.contains(lang.toString().toLowerCase())) {
+ pass = false;
+ sb.append(indent + indent + "Content-Type test failed: ").append(lang)
+ .append(" is not expected in Response").append(newline);
+ }
+ }
+ }
+ }
+
+ if (ccl != null) {
+ for (String tt : ccl) {
+ sb.append("Expecting Cache-Control ").append(tt).append(newline);
+ }
+ if (key.equalsIgnoreCase("Cache-Control")) {
+ for (Object all_ccl : mvp.get(key)) {
+ for (String cc : ccl) {
+ if (!(all_ccl.toString().toLowerCase().contains(cc.toLowerCase()))) {
+ pass = false;
+ sb.append(indent + indent + "Cache-Control test failed: ").append(cc)
+ .append(" is not found in Response.").append(newline);
+ }
+ }
+ }
+ }
+ }
+
+ if (cookies != null) {
+ for (String tt : cookies) {
+ sb.append(indent + indent + "Expecting Set-Cookie").append(tt).append(newline);
+ }
+ if (key.equalsIgnoreCase("Set-Cookie")) {
+ for (Object nck_actual : mvp.get(key)) {
+ sb.append(indent + indent + "Processing ").append(nck_actual.toString()).append(newline);
+ if (!cookies.contains(nck_actual.toString().toLowerCase()
+ .replace(" ", ""))) {
+ pass = false;
+ sb.append(indent + indent + "Set-Cookie test failed: ").append(nck_actual)
+ .append(" is not expected in Response.").append(newline);
+ } else {
+ sb.append(indent + indent + "Expected Set-Cookie: ").append(nck_actual)
+ .append(" is found in Response.").append(newline);
+ }
+ }
+ }
+ }
+ }
+
+ sb.append(indent).append(pass);
+
+ return sb.toString();
+ }
+
+ private String verifyResponse(Response resp, String content, int status, HashMap<String, String> expected_map) {
+ boolean pass = true;
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("========== Verifying a Response with Map: ").append(newline);
+
+ if ((content == null) || (content.equals(""))) {
+ if (!(resp.getEntity() == null) || "".equals(resp.getEntity())) {
+ pass = false;
+ sb.append(indent + "Entity verification failed: expecting no content, got ").append((String) resp.getEntity())
+ .append(newline);
+ }
+ } else if (!content.equals(resp.getEntity())) {
+ pass = false;
+ sb.append(indent + "Entity verification failed: expecting ").append(content).append(", got ")
+ .append((String) resp.getEntity()).append(newline);
+ } else {
+ sb.append(indent + "Correct content found in Response: ").append((String) resp.getEntity()).append(newline);
+ }
+
+ if (resp.getStatus() != status) {
+ pass = false;
+ sb.append(indent + "Status code verification failed: expecting ").append(status).append(", got ")
+ .append(resp.getStatus()).append(newline);
+ } else {
+ sb.append(indent + "Correct status found in Response: ").append(status).append(newline);
+ }
+
+ MultivaluedMap<java.lang.String, java.lang.Object> mvp =
+ resp.getMetadata();
+ if (expected_map == null) {
+ sb.append(indent + "No keys to verify or expected, but found the following keys in Response:").append(newline);
+ for (String key : mvp.keySet()) {
+ sb.append(indent + indent + "Key: ").append(key).append("; ").append(mvp.getFirst(key)).append(";")
+ .append(newline);
+ }
+ } else {
+ for (String key_actual : mvp.keySet()) {
+ sb.append(indent + "Response contains key: ").append(key_actual).append(newline);
+ }
+ sb.append(indent + "Verifying the following keys in Response:").append(newline);
+ String actual, expected;
+ for (String key : expected_map.keySet()) {
+ if (!mvp.containsKey(key)) {
+ pass = false;
+ sb.append(indent + indent + "Key: ").append(key).append(" is not found in Response;").append(newline);
+ } else if (key.equalsIgnoreCase("last-modified")) {
+ sb.append(indent + indent + "Key Last-Modified is found in response").append(newline);
+ } else {
+ expected = expected_map.get(key).toLowerCase();
+ actual = mvp.getFirst(key).toString().toLowerCase();
+
+ if (actual.startsWith("\"") && actual.endsWith("\"")) {
+ actual = actual.substring(1, actual.length() - 1);
+ }
+
+ if (!actual.equals(expected)) {
+ pass = false;
+ sb.append(indent + indent + "Key: ").append(key).append(" found in Response, but with different value;")
+ .append(newline);
+ sb.append(indent + indent + "Expecting ").append(expected_map.get(key)).append("; got ")
+ .append(mvp.getFirst(key)).append(newline);
+ }
+ sb.append(indent + indent + "Processed key ").append(key).append(" with expected value ")
+ .append(expected_map.get(key)).append(newline);
+ }
+ }
+ }
+ sb.append(indent).append(pass);
+ return sb.toString();
+ }
+
+ @Test
+ public void testAllowString() {
+ Response.ResponseBuilder responseBuilder = Response.ok();
+
+ responseBuilder = responseBuilder.allow("GET");
+ assertTrue(responseBuilder.build().getHeaderString(HttpHeaders.ALLOW).contains("GET"));
+ responseBuilder = responseBuilder.allow((String) null);
+ assertTrue(responseBuilder.build().getHeaderString(HttpHeaders.ALLOW) == null);
+ }
+
+ @Test
+ public void testAllowSet() {
+ Response.ResponseBuilder responseBuilder = Response.ok();
+
+ responseBuilder = responseBuilder.allow(new HashSet<>(Arrays.asList("GET")));
+ assertTrue(responseBuilder.build().getHeaderString(HttpHeaders.ALLOW).contains("GET"));
+ responseBuilder = responseBuilder.allow((Set<String>) null);
+ assertEquals(null, responseBuilder.build().getHeaderString(HttpHeaders.ALLOW));
+ }
+
+ @Test
+ public void testAllowVariant() {
+ Response.ResponseBuilder responseBuilder = Response.ok();
+
+ responseBuilder = responseBuilder.allow(new HashSet<>(Arrays.asList("GET")));
+ assertTrue(responseBuilder.build().getHeaderString(HttpHeaders.ALLOW).contains("GET"));
+ responseBuilder = responseBuilder.allow((String[]) null);
+ assertEquals(null, responseBuilder.build().getHeaderString(HttpHeaders.ALLOW));
+ }
+
+ @Test
+ public void bufferEntityTest() {
+ Response response = Response.ok().build();
+ response.close();
+ try {
+ response.bufferEntity();
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void getEntityTest() {
+ Response response = Response.ok().build();
+ response.close();
+ try {
+ response.getEntity();
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void hasEntityTest() {
+ Response response = Response.ok().build();
+ response.close();
+ try {
+ response.hasEntity();
+ fail("IllegalStateException expected when reading entity after response has been closed.");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ // Reproducer for JERSEY-1553
+ @Test
+ public void testVariants() {
+ List<String> encoding = Arrays.asList("gzip", "compress");
+ List<Variant> list = Variant.VariantListBuilder
+ .newInstance()
+ .mediaTypes(MediaType.TEXT_PLAIN_TYPE)
+ .languages(new Locale("en", "US"), new Locale("en", "GB"))
+ .encodings(encoding.toArray(new String[encoding.size()])).add().build();
+
+ final Response r1 = Response.ok().variants(list).build();
+ assertNotNull(r1);
+ assertNotNull(r1.getHeaderString(HttpHeaders.VARY));
+
+ final Response r2 = Response.ok().variants(list.toArray(new Variant[list.size()])).build();
+ assertNotNull(r2);
+ assertNotNull(r2.getHeaderString(HttpHeaders.VARY));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/RestrictedHeaderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/RestrictedHeaderTest.java
new file mode 100644
index 0000000..06568bd
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/RestrictedHeaderTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test setting headers that are restricted by {@link java.net.HttpURLConnection}.
+ *
+ * @author Miroslav Fuksa
+ */
+public class RestrictedHeaderTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(RestrictedHeaderTest.class.getName());
+
+ @Path("/")
+ public static class MyResource {
+
+ @GET
+ public Response getOptions(@Context HttpHeaders headers) {
+ MultivaluedMap<String, String> requestHeaders = headers.getRequestHeaders();
+ System.out.println("Headers: " + requestHeaders);
+ if (requestHeaders.containsKey("Origin") || requestHeaders.containsKey("Access-Control-Request-Method")) {
+ LOGGER.info("CORS headers found.");
+ return Response.ok().build();
+ }
+ LOGGER.info("CORS headers are missing. ");
+ return Response.serverError().entity("CORS headers are missing").build();
+ }
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new ResourceConfig(MyResource.class, LoggingFeature.class);
+ }
+
+ @Ignore("The setting of allowRestrictedHeaders system property is global and cached. Only "
+ + "one of both testForbiddenHeadersNotAllowed() and testForbiddenHeadersAllowed() can be run during one test.")
+ @Test
+ public void testForbiddenHeadersNotAllowed() {
+ Client client = ClientBuilder.newClient();
+ Response response = testHeaders(client);
+ Assert.assertEquals(500, response.getStatus());
+ }
+
+ /**
+ * Tests sending of restricted headers (Origin and Access-Control-Request-Method) which are
+ * used for CORS. These headers are by default skipped by the {@link java.net.HttpURLConnection}.
+ * The system property {@code sun.net.http.allowRestrictedHeaders} must be defined in order to
+ * allow these headers.
+ */
+ @Test
+ public void testForbiddenHeadersAllowed() {
+ Client client = ClientBuilder.newClient();
+ System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+
+ Response response = testHeaders(client);
+ System.out.println(response.readEntity(String.class));
+ Assert.assertEquals(200, response.getStatus());
+ }
+
+ /**
+ * Same as {@link #testForbiddenHeadersAllowed()} ()} but uses {@link org.glassfish.jersey.apache.connector
+ * .ApacheConnector} connector
+ * which allows modification of these headers.
+ */
+ @Test
+ public void testForbiddenHeadersWithApacheConnector() {
+ ClientConfig clientConfig = new ClientConfig();
+ clientConfig.connectorProvider(new ApacheConnectorProvider());
+ Client client = ClientBuilder.newClient(clientConfig);
+ testHeaders(client);
+ }
+
+ private Response testHeaders(Client client) {
+ client.register(LoggingFeature.class);
+ Invocation.Builder builder = client.target(getBaseUri()).path("/").request()
+ .header("Origin", "http://example.com")
+ .header("Access-Control-Request-Method", "POST")
+ .header("Testus", "Hello");
+ return builder.get();
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/SourceEntityProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/SourceEntityProviderTest.java
new file mode 100644
index 0000000..47b6173
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/SourceEntityProviderTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test of {@link javax.xml.transform.Source Source} MessageBody Provider
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class SourceEntityProviderTest extends JerseyTest {
+
+ private static final String prefix = "<?xml version=\"1.0\" encoding=\"UTF-8\"";
+ private static final String xdkPrefix = "<?xml version = '1.0' encoding = 'UTF-8'?>";
+ private static final String entity = prefix + "?><test><aaa/></test>";
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ private static String extractContent(Source source) throws TransformerFactoryConfigurationError,
+ TransformerConfigurationException, TransformerException {
+ TransformerFactory transFactory = TransformerFactory.newInstance();
+
+ // identity transformation
+ Transformer transformer = transFactory.newTransformer();
+
+ StringWriter writer = new StringWriter();
+ Result result = new StreamResult(writer);
+ transformer.transform(source, result);
+ return writer.toString();
+ }
+
+ @Test
+ public void sourceProviderTest() throws IOException, TransformerConfigurationException, TransformerFactoryConfigurationError,
+ TransformerException {
+ Source source = new StreamSource(new ByteArrayInputStream(entity.getBytes()));
+
+ Response response = target().path("test").path("source").request().put(Entity.entity(source, MediaType.TEXT_XML_TYPE));
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith(StreamSource.class.toString()));
+ }
+
+ @Test
+ public void streamProviderTest() throws IOException {
+ StreamSource source = new StreamSource(new ByteArrayInputStream(entity.getBytes()));
+
+ Response response = target().path("test").path("stream").request().put(Entity.entity(source, MediaType.TEXT_XML_TYPE));
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith(StreamSource.class.toString()));
+ }
+
+ @Test
+ public void saxProviderTest() throws IOException, SAXException, ParserConfigurationException {
+ SAXSource source = createSAXSource(entity);
+
+ Response response = target().path("test").path("sax").request().put(Entity.entity(source, MediaType.TEXT_XML_TYPE));
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith(SAXSource.class.toString()));
+ }
+
+ @Test
+ public void domProviderTest() throws IOException, SAXException, ParserConfigurationException {
+ DOMSource source = createDOMSoruce(entity);
+
+ Response response = target().path("test").path("dom").request().put(Entity.entity(source, MediaType.TEXT_XML_TYPE));
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith(DOMSource.class.toString()));
+ }
+
+ @Test
+ public void getSourceTest() throws Exception {
+ Response response = target().path("test").path("source").request().get();
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ String content = extractContent(response.readEntity(Source.class));
+ assertTrue(content.startsWith(prefix) || content.startsWith(xdkPrefix));
+ }
+
+ @Test
+ public void getStreamSourceTest() throws Exception {
+ Response response = target().path("test").path("stream").request().get();
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ String content = extractContent(response.readEntity(StreamSource.class));
+ assertTrue(content.startsWith(prefix) || content.startsWith(xdkPrefix));
+ }
+
+ @Test
+ public void getSaxSourceTest() throws Exception {
+ Response response = target().path("test").path("sax").request().get();
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ String content = extractContent(response.readEntity(SAXSource.class));
+ assertTrue("Content '" + content + "' does not start with the expected prefix '" + prefix + "'",
+ content.startsWith(prefix) || content.startsWith(xdkPrefix));
+ }
+
+ @Test
+ public void getDomSourceTest() throws Exception {
+ Response response = target().path("test").path("dom").request().get();
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ String content = extractContent(response.readEntity(DOMSource.class));
+ assertTrue("Content '" + content + "' does not start with the expected prefix '" + prefix + "'",
+ content.startsWith(prefix) || content.startsWith(xdkPrefix));
+ }
+
+ private static SAXSource createSAXSource(String content) throws SAXException, ParserConfigurationException {
+ SAXParserFactory saxFactory = SAXParserFactory.newInstance();
+ return new SAXSource(saxFactory.newSAXParser().getXMLReader(), new InputSource(new ByteArrayInputStream(
+ content.getBytes())));
+ }
+
+ private static DOMSource createDOMSoruce(String content) throws SAXException, IOException, ParserConfigurationException {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ Document d = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(content.getBytes()));
+ return new DOMSource(d);
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @PUT
+ @Consumes("text/xml")
+ @Path("source")
+ public String putSourceAndReturnString(Source source) throws IOException, TransformerException {
+ return source.getClass() + extractContent(source);
+ }
+
+ @PUT
+ @Consumes("text/xml")
+ @Path("stream")
+ public String putStreamSourceAndReturnString(StreamSource source) throws IOException, TransformerException {
+ return source.getClass() + extractContent(source);
+ }
+
+ @PUT
+ @Consumes("text/xml")
+ @Path("sax")
+ public String putSaxSourceAndReturnString(SAXSource source) throws IOException, TransformerException {
+ return source.getClass() + extractContent(source);
+ }
+
+ @PUT
+ @Consumes("text/xml")
+ @Path("dom")
+ public String putDomSourceAndReturnString(DOMSource source) throws IOException, TransformerException {
+ return source.getClass() + extractContent(source);
+ }
+
+ @GET
+ @Produces("application/xml")
+ @Path("source")
+ public StreamSource getSource() {
+ return new StreamSource(new ByteArrayInputStream(entity.getBytes()));
+ }
+
+ @GET
+ @Produces("application/xml")
+ @Path("stream")
+ public StreamSource getStreamSource() {
+ return new StreamSource(new ByteArrayInputStream(entity.getBytes()));
+ }
+
+ @GET
+ @Produces("application/xml")
+ @Path("sax")
+ public SAXSource getSaxSource() throws SAXException, ParserConfigurationException {
+ return createSAXSource(entity);
+ }
+
+ @GET
+ @Produces("application/xml")
+ @Path("dom")
+ public DOMSource getDomSource() throws Exception {
+ return createDOMSoruce(entity);
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/UnsafeCharsInUriTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/UnsafeCharsInUriTest.java
new file mode 100644
index 0000000..79edd3f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/UnsafeCharsInUriTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.URI;
+import java.nio.charset.Charset;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+
+/**
+ * Test if URI can contain unsafe characters in the query parameter, e.g. for sending JSON
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class UnsafeCharsInUriTest extends JerseyTest {
+ @Override
+ protected ResourceConfig configure() {
+ ResourceConfig rc = new ResourceConfig(UnsafeCharsInUriTest.ResponseTest.class);
+ return rc;
+ }
+
+ /**
+ * Test resource
+ */
+ @Path(value = "/app")
+ public static class ResponseTest {
+ /**
+ * Test resource method returning the content of the {@code msg} query parameter.
+ *
+ * @return the {@code msg} query parameter (as received)
+ */
+ @GET
+ @Path("test")
+ public Response jsonQueryParamTest(@DefaultValue("") @QueryParam("msg") final String msg) {
+ return Response.ok().entity(msg).build();
+ }
+
+ }
+
+ /**
+ * Test, that server can consume JSON (curly brackets) and other unsafe characters sent in the query parameter
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testSpecCharsInUriWithSockets() throws IOException {
+ // quotes are encoded by browsers, curly brackets are not, so the quotes will be sent pre-encoded
+ // HTTP 1.0 is used for simplicity
+ String response = sendGetRequestOverSocket(getBaseUri(), "GET /app/test?msg={%22foo%22:%22bar%22} HTTP/1.0");
+ assertArrayEquals("{\"foo\":\"bar\"}".getBytes(Charset.forName("ISO-8859-1")), response.getBytes());
+ }
+
+ @Test
+ @Ignore("Incorrectly written test (doesn't deal with http encoding).")
+ public void testSecialCharsInQueryParam() throws IOException {
+ // quotes are encoded by browsers, curly brackets are not, so the quotes will be sent pre-encoded
+ // HTTP 1.0 is used for simplicity
+ String response = sendGetRequestOverSocket(getBaseUri(),
+ "GET /app/test?msg=Hello\\World+With+SpecChars+§*)$!±@-_=;`:\\,~| HTTP/1.0");
+
+ assertArrayEquals("Hello\\World With SpecChars §*)$!±@-_=;`:\\,~|".getBytes(Charset.forName("ISO-8859-1")),
+ response.getBytes());
+ }
+
+ private String sendGetRequestOverSocket(final URI baseUri, final String requestLine) throws IOException {
+ // Low level approach with sockets is used, because common Java HTTP clients are using java.net.URI,
+ // which fails when unencoded curly bracket is part of the URI
+ final Socket socket = new Socket(baseUri.getHost(), baseUri.getPort());
+ final PrintWriter pw =
+ new PrintWriter(
+ new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), Charset.forName("ISO-8859-1"))));
+
+ pw.println(requestLine);
+ pw.println(); // http request should end with a blank line
+ pw.flush();
+
+ final BufferedReader br =
+ new BufferedReader(new InputStreamReader(socket.getInputStream(), Charset.forName("UTF-8")));
+
+ String lastLine = null;
+ String line;
+ while ((line = br.readLine()) != null) {
+ // read the response and remember the last line
+ lastLine = line;
+ }
+ pw.close();
+ br.close();
+
+ return lastLine;
+ }
+}
+
+
+
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/VariantsTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/VariantsTest.java
new file mode 100644
index 0000000..b6c0f74
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/VariantsTest.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.api;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Server-side variant selection & handling test.
+ *
+ * @author Paul Sandoz
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class VariantsTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(
+ LanguageVariantResource.class,
+ ComplexVariantResource.class,
+ MediaTypeQualitySourceResource.class);
+ }
+
+ @Path("/lvr")
+ public static class LanguageVariantResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ List<Variant> vs = Variant.VariantListBuilder.newInstance()
+ .languages(new Locale("zh"))
+ .languages(new Locale("fr"))
+ .languages(new Locale("en"))
+ .add()
+ .build();
+
+ Variant v = r.selectVariant(vs);
+ if (v == null) {
+ return Response.notAcceptable(vs).build();
+ } else {
+ return Response.ok(v.getLanguage().toString(), v).build();
+ }
+ }
+ }
+
+ @Test
+ public void testGetLanguageEn() throws IOException {
+ WebTarget rp = target("/lvr");
+
+ Response r = rp.request()
+ .header("Accept-Language", "en")
+ .get();
+ assertEquals("en", r.readEntity(String.class));
+ assertEquals("en", r.getLanguage().toString());
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(!contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Test
+ public void testGetLanguageZh() throws IOException {
+ WebTarget rp = target("/lvr");
+
+ Response r = rp.request()
+ .header("Accept-Language", "zh")
+ .get();
+ assertEquals("zh", r.readEntity(String.class));
+ assertEquals("zh", r.getLanguage().toString());
+ System.out.println(r.getMetadata().getFirst("Vary"));
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(!contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Test
+ public void testGetLanguageMultiple() throws IOException {
+ WebTarget rp = target("/lvr");
+
+ Response r = rp
+ .request()
+ .header("Accept-Language", "en;q=0.3, zh;q=0.4, fr")
+ .get();
+ assertEquals("fr", r.readEntity(String.class));
+ assertEquals("fr", r.getLanguage().toString());
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(!contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Path("/cvr")
+ public static class ComplexVariantResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ List<Variant> vs = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.valueOf("image/jpeg"))
+ .add()
+ .mediaTypes(MediaType.valueOf("application/xml"))
+ .languages(new Locale("en", "us"))
+ .add()
+ .mediaTypes(MediaType.valueOf("text/xml"))
+ .languages(new Locale("en"))
+ .add()
+ .mediaTypes(MediaType.valueOf("text/xml"))
+ .languages(new Locale("en", "us"))
+ .add()
+ .build();
+
+ Variant v = r.selectVariant(vs);
+ if (v == null) {
+ return Response.notAcceptable(vs).build();
+ } else {
+ return Response.ok("GET", v).build();
+ }
+ }
+ }
+
+ @Test
+ public void testGetComplex1() throws IOException {
+ WebTarget rp = target("/cvr");
+
+ Response r = rp.request("text/xml",
+ "application/xml",
+ "application/xhtml+xml",
+ "image/png",
+ "text/html;q=0.9",
+ "text/plain;q=0.8",
+ "*/*;q=0.5")
+ .header("Accept-Language", "en-us,en;q=0.5")
+ .get();
+ assertEquals("GET", r.readEntity(String.class));
+ assertEquals(MediaType.valueOf("text/xml"), r.getMediaType());
+ assertEquals("en", r.getLanguage().getLanguage());
+ assertEquals("US", r.getLanguage().getCountry());
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Test
+ public void testGetComplex2() throws IOException {
+ WebTarget rp = target("/cvr");
+
+ Response r = rp.request("text/xml",
+ "application/xml",
+ "application/xhtml+xml",
+ "image/png",
+ "text/html;q=0.9",
+ "text/plain;q=0.8",
+ "*/*;q=0.5")
+ .header("Accept-Language", "en,en-us")
+ .get();
+ assertEquals("GET", r.readEntity(String.class));
+ assertEquals(MediaType.valueOf("text/xml"), r.getMediaType());
+ assertEquals("en", r.getLanguage().toString());
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Test
+ public void testGetComplex3() throws IOException {
+ WebTarget rp = target("/cvr");
+
+ Response r = rp.request("application/xml",
+ "text/xml",
+ "application/xhtml+xml",
+ "image/png",
+ "text/html;q=0.9",
+ "text/plain;q=0.8",
+ "*/*;q=0.5")
+ .header("Accept-Language", "en-us,en;q=0.5")
+ .get();
+ assertEquals("GET", r.readEntity(String.class));
+ assertEquals(MediaType.valueOf("application/xml"), r.getMediaType());
+ assertEquals("en", r.getLanguage().getLanguage());
+ assertEquals("US", r.getLanguage().getCountry());
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ }
+
+ @Test
+ public void testGetComplexNotAcceptable() throws IOException {
+ WebTarget rp = target("/cvr");
+
+ Response r = rp.request("application/atom+xml")
+ .header("Accept-Language", "en-us,en")
+ .get();
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ assertEquals(406, r.getStatus());
+
+ r = rp.request("application/xml")
+ .header("Accept-Language", "fr")
+ .get();
+ vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ assertTrue(contains(vary, "Accept-Language"));
+ assertEquals(406, r.getStatus());
+ }
+
+ @Path("/mtqsr")
+ public static class MediaTypeQualitySourceResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ List<Variant> vs = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.valueOf("application/xml;qs=0.8"))
+ .mediaTypes(MediaType.valueOf("text/html;qs=1.0"))
+ .add()
+ .build();
+
+ Variant v = r.selectVariant(vs);
+ if (v == null) {
+ return Response.notAcceptable(vs).build();
+ } else {
+ return Response.ok("GET", v).build();
+ }
+ }
+ }
+
+ @Test
+ public void testMediaTypeQualitySource() throws IOException {
+ WebTarget rp = target("/mtqsr");
+
+ Response r = rp.request(
+ "application/xml",
+ "text/html;q=0.9")
+ .get();
+ assertTrue(MediaTypes.typeEqual(MediaType.valueOf("text/html"), r.getMediaType()));
+ String vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+
+ r = rp.request(
+ "text/html",
+ "application/xml")
+ .get();
+ assertTrue(MediaTypes.typeEqual(MediaType.valueOf("text/html"), r.getMediaType()));
+ vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+
+ r = rp.request(
+ "application/xml",
+ "text/html")
+ .get();
+ assertTrue(MediaTypes.typeEqual(MediaType.valueOf("text/html"), r.getMediaType()));
+ vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+
+ r = rp.request(
+ "application/xml")
+ .get();
+ assertTrue(MediaTypes.typeEqual(MediaType.valueOf("application/xml"), r.getMediaType()));
+ vary = r.getHeaderString("Vary");
+ assertNotNull(vary);
+ assertTrue(contains(vary, "Accept"));
+ }
+
+ private boolean contains(String l, String v) {
+ String[] vs = l.split(",");
+ for (String s : vs) {
+ s = s.trim();
+ if (s.equalsIgnoreCase(v)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java
new file mode 100644
index 0000000..9fedb4d
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ClientTest extends JerseyTest {
+
+ @Path("helloworld")
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN)
+ public static class HelloWorldResource {
+
+ private static final String MESSAGE = "Hello world!";
+
+ @GET
+ public String getClichedMessage() {
+ return MESSAGE;
+ }
+ }
+
+ @Path("headers")
+ @Produces(MediaType.TEXT_PLAIN)
+ public static class HeadersTestResource {
+
+ @POST
+ @Path("content")
+ public String contentHeaders(@HeaderParam("custom-header") final String customHeader,
+ @Context final HttpHeaders headers, final String entity) {
+ final StringBuilder sb = new StringBuilder(entity).append('\n');
+
+ sb.append("custom-header:").append(customHeader).append('\n');
+
+ for (final Map.Entry<String, List<String>> header : headers.getRequestHeaders().entrySet()) {
+ sb.append(header.getKey()).append(':').append(header.getValue().toString()).append('\n');
+ }
+
+ return sb.toString();
+ }
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class, HeadersTestResource.class);
+ }
+
+ @Test
+ public void testAccesingHelloworldResource() {
+ final WebTarget resource = target().path("helloworld");
+ final Response r = resource.request().get();
+ assertEquals(200, r.getStatus());
+
+ final String responseMessage = resource.request().get(String.class);
+ assertEquals(HelloWorldResource.MESSAGE, responseMessage);
+ }
+
+ @Test
+ public void testAccesingMissingResource() {
+ final WebTarget missingResource = target().path("missing");
+ final Response r = missingResource.request().get();
+ assertEquals(404, r.getStatus());
+
+
+ try {
+ missingResource.request().get(String.class);
+ } catch (final WebApplicationException ex) {
+ assertEquals(404, ex.getResponse().getStatus());
+ return;
+ }
+
+ fail("Expected WebApplicationException has not been thrown.");
+ }
+
+ @Test
+ // Inspired by JERSEY-1502
+ public void testContextHeaders() {
+ final WebTarget target = target().path("headers").path("content");
+
+ Invocation.Builder ib;
+ Invocation i;
+ Response r;
+ String reqHeaders;
+
+ ib = target.request("*/*");
+ ib.header("custom-header", "custom-value");
+ ib.header("content-encoding", "deflate");
+ i = ib.build("POST", Entity.entity("aaa", MediaType.WILDCARD_TYPE));
+ r = i.invoke();
+
+ reqHeaders = r.readEntity(String.class).toLowerCase();
+ for (final String expected : new String[] {"custom-header:[custom-value]", "custom-header:custom-value"}) {
+ assertTrue(String.format("Request headers do not contain expected '%s' entry:\n%s", expected, reqHeaders),
+ reqHeaders.contains(expected));
+ }
+ final String unexpected = "content-encoding";
+ assertFalse(String.format("Request headers contains unexpected '%s' entry:\n%s", unexpected, reqHeaders),
+ reqHeaders.contains(unexpected));
+
+ ib = target.request("*/*");
+ i = ib.build("POST",
+ Entity.entity("aaa", Variant.mediaTypes(MediaType.WILDCARD_TYPE).encodings("deflate").build().get(0)));
+ r = i.invoke();
+
+ final String expected = "content-encoding:[deflate]";
+ reqHeaders = r.readEntity(String.class).toLowerCase();
+ assertTrue(String.format("Request headers do not contain expected '%s' entry:\n%s", expected, reqHeaders),
+ reqHeaders.contains(expected));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ExecutorServiceProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ExecutorServiceProviderTest.java
new file mode 100644
index 0000000..c97f574
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ExecutorServiceProviderTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientAsyncExecutor;
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import org.glassfish.jersey.server.ManagedAsync;
+import org.glassfish.jersey.server.ManagedAsyncExecutor;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.spi.ExecutorServiceProvider;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * {@link org.glassfish.jersey.spi.ExecutorServiceProvider} E2E tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ExecutorServiceProviderTest extends JerseyTest {
+
+ @Path("resource")
+ @Produces("text/plain")
+ public static class TestResourceA {
+
+ @GET
+ public String getSync() {
+ return "resource";
+ }
+
+ @GET
+ @Path("async")
+ @ManagedAsync
+ public String getAsync() {
+ return "async-resource-" + ExecutorServiceProviderTest.getResponseOnThread();
+ }
+ }
+
+ // A separate resource class for the custom-async sub-path to ensure that
+ // the named ExecutorService injection is only performed for the "/resource/custom-async" path.
+ @Path("resource")
+ @Produces("text/plain")
+ public static class TestResourceB {
+
+ @Inject
+ @Named("custom")
+ ExecutorService executorService;
+
+ @GET
+ @Path("custom-async")
+ public void getCustomAsync(@Suspended final AsyncResponse asyncResponse) {
+ executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ asyncResponse.resume("custom-async-resource-" + ExecutorServiceProviderTest.getResponseOnThread());
+ }
+ });
+ }
+ }
+
+ static String getResponseOnThread() {
+ final String threadName = Thread.currentThread().getName();
+ if (threadName.startsWith("async-request-")) {
+ return "passed";
+ } else {
+ return "error - unexpected custom thread name: " + threadName;
+ }
+ }
+
+ @ClientAsyncExecutor
+ @ManagedAsyncExecutor
+ @Named("custom")
+ public static class CustomExecutorProvider implements ExecutorServiceProvider {
+
+ private final Set<ExecutorService> executors = Collections.newSetFromMap(new IdentityHashMap<>());
+ private volatile int executorCreationCount = 0;
+ private volatile int executorReleaseCount = 0;
+
+ public void reset() {
+ for (ExecutorService executor : executors) {
+ executor.shutdownNow();
+ }
+
+ executors.clear();
+ executorCreationCount = 0;
+ executorReleaseCount = 0;
+ }
+
+ @Override
+ public ExecutorService getExecutorService() {
+ return new CustomExecutorService();
+ }
+
+ @Override
+ public void dispose(final ExecutorService executorService) {
+ executorService.shutdownNow();
+ }
+
+ private class CustomExecutorService implements ExecutorService {
+
+ private final ExecutorService delegate;
+ private final AtomicBoolean isCleanedUp;
+
+ public CustomExecutorService() {
+ this.isCleanedUp = new AtomicBoolean(false);
+ this.delegate = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
+ .setNameFormat("async-request-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .build());
+
+ executorCreationCount++;
+ executors.add(this);
+ }
+
+ @Override
+ public void shutdown() {
+ tryCleanUp();
+ delegate.shutdown();
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ tryCleanUp();
+ return delegate.shutdownNow();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return delegate.isShutdown();
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return delegate.isTerminated();
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return delegate.awaitTermination(timeout, unit);
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return delegate.submit(task);
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return delegate.submit(task, result);
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return delegate.submit(task);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
+ return delegate.invokeAll(tasks);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate.invokeAll(tasks, timeout, unit);
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
+ return delegate.invokeAny(tasks);
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate.invokeAny(tasks, timeout, unit);
+ }
+
+ private void tryCleanUp() {
+ if (isCleanedUp.compareAndSet(false, true)) {
+ executors.remove(this);
+ executorReleaseCount++;
+ }
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ delegate.execute(command);
+ }
+ }
+ }
+
+ private static final CustomExecutorProvider serverExecutorProvider = new CustomExecutorProvider();
+
+ @Override
+ protected Application configure() {
+ // enable(TestProperties.LOG_TRAFFIC);
+ // enable(TestProperties.DUMP_ENTITY);
+ return new ResourceConfig(TestResourceA.class, TestResourceB.class).register(serverExecutorProvider);
+ }
+
+ /**
+ * Reproducer for JERSEY-2205 (client-side).
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testCustomClientExecutorsInjectionAndReleasing() throws Exception {
+ final CustomExecutorProvider provider = new CustomExecutorProvider();
+ Client client = ClientBuilder.newClient().register(provider);
+
+ Response response = client.target(getBaseUri()).path("resource").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("resource", response.readEntity(String.class));
+
+ // no executors should be created or released at this point yet
+ assertEquals("Unexpected number of created client executors", 0, provider.executorCreationCount);
+ assertEquals("Unexpected number of released client executors", 0, provider.executorReleaseCount);
+ assertEquals("Unexpected number of client executors stored in the set.",
+ 0, provider.executors.size());
+
+ Future<Response> fr = client.target(getBaseUri()).path("resource").request().async().get();
+ response = fr.get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("resource", response.readEntity(String.class));
+
+ // single executor should be created but not released at this point yet
+ assertEquals("Unexpected number of created client executors", 1, provider.executorCreationCount);
+ assertEquals("Unexpected number of released client executors", 0, provider.executorReleaseCount);
+ assertEquals("Unexpected number of client executors stored in the set.",
+ 1, provider.executors.size());
+
+ client.close();
+
+ // the created executor needs to be released by now; no more executors should be created
+ assertEquals("Unexpected number of created client executors", 1, provider.executorCreationCount);
+ assertEquals("Unexpected number of released client executors", 1, provider.executorReleaseCount);
+ assertEquals("Unexpected number of client executors stored in the set.",
+ 0, provider.executors.size());
+ }
+
+ /**
+ * Reproducer for JERSEY-2205 (server-side).
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testCustomServerExecutorsInjectionAndReleasing() throws Exception {
+ // reset server executor statistics to avoid data pollution from other test methods
+ serverExecutorProvider.reset();
+
+ Response response = target("resource").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("resource", response.readEntity(String.class));
+
+ // no executors should be created or released at this point yet
+ assertEquals("Unexpected number of created server executors", 0, serverExecutorProvider.executorCreationCount);
+ assertEquals("Unexpected number of released server executors", 0, serverExecutorProvider.executorReleaseCount);
+ assertEquals("Unexpected number of server executors stored in the set.",
+ 0, serverExecutorProvider.executors.size());
+
+ response = target("resource/async").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("async-resource-passed", response.readEntity(String.class));
+
+ // single executor should be created but not released at this point yet
+ assertEquals("Unexpected number of created server executors", 1, serverExecutorProvider.executorCreationCount);
+ assertEquals("Unexpected number of released server executors", 0, serverExecutorProvider.executorReleaseCount);
+ assertEquals("Unexpected number of server executors stored in the set.",
+ 1, serverExecutorProvider.executors.size());
+
+ tearDown(); // stopping test container
+
+ // the created executor needs to be released by now; no more executors should be created
+ assertEquals("Unexpected number of created server executors", 1, serverExecutorProvider.executorCreationCount);
+ assertEquals("Unexpected number of released server executors", 1, serverExecutorProvider.executorReleaseCount);
+ assertEquals("Unexpected number of server executors stored in the set.",
+ 0, serverExecutorProvider.executors.size());
+
+ setUp(); // re-starting test container to ensure proper post-test tearDown.
+ }
+
+ /**
+ * Test named custom executor injection and release mechanism.
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testCustomNamedServerExecutorsInjectionAndReleasing() throws Exception {
+ serverExecutorProvider.reset();
+
+ Response response = target("resource/custom-async").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("custom-async-resource-passed", response.readEntity(String.class));
+
+ // single executor should be created but not released at this point yet
+ assertEquals("Unexpected number of created server executors", 1, serverExecutorProvider.executorCreationCount);
+ assertEquals("Unexpected number of released server executors", 0, serverExecutorProvider.executorReleaseCount);
+ assertEquals("Unexpected number of server executors stored in the set.",
+ 1, serverExecutorProvider.executors.size());
+
+ tearDown(); // stopping test container
+
+ // the created executor needs to be released by now; no more executors should be created
+ assertEquals("Unexpected number of created server executors", 1, serverExecutorProvider.executorCreationCount);
+ assertEquals("Unexpected number of released server executors", 1, serverExecutorProvider.executorReleaseCount);
+ assertEquals("Unexpected number of server executors stored in the set.",
+ 0, serverExecutorProvider.executors.size());
+
+ setUp(); // re-starting test container to ensure proper post-test tearDown.
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorCustomTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorCustomTest.java
new file mode 100644
index 0000000..b2aac95
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorCustomTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.InterceptorContext;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.tests.e2e.InterceptorGzipTest.GZIPReaderTestInterceptor;
+import org.glassfish.jersey.tests.e2e.InterceptorGzipTest.GZIPWriterTestInterceptor;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests interceptors.
+ *
+ * @author Miroslav Fuksa
+ * @author Michal Gajdos
+ */
+public class InterceptorCustomTest extends JerseyTest {
+
+ private static final String FROM_RESOURCE = "-from_resource";
+ private static final String ENTITY = "hello, this is text entity";
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(TestResource.class, GZIPWriterTestInterceptor.class, GZIPReaderTestInterceptor.class,
+ PlusOneWriterInterceptor.class, MinusOneReaderInterceptor.class, AnnotationsReaderWriterInterceptor.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(GZIPReaderTestInterceptor.class)
+ .register(GZIPWriterTestInterceptor.class)
+ .register(PlusOneWriterInterceptor.class)
+ .register(MinusOneReaderInterceptor.class)
+ .register(AnnotationsReaderWriterInterceptor.class);
+ }
+
+ @Test
+ public void testMoreInterceptorsAndFilter() throws IOException {
+ WebTarget target = target().path("test");
+
+ Response response = target.request().put(Entity.entity(ENTITY, MediaType.TEXT_PLAIN_TYPE));
+ String str = response.readEntity(String.class);
+ assertEquals(ENTITY + FROM_RESOURCE, str);
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @PUT
+ @Produces("text/plain")
+ @Consumes("text/plain")
+ public String put(String str) {
+ System.out.println("resource: " + str);
+ return str + FROM_RESOURCE;
+ }
+ }
+
+ /**
+ * Interceptor which adds +1 to each byte written into the stream.
+ */
+ @Provider
+ @Priority(300)
+ public static class PlusOneWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final OutputStream old = context.getOutputStream();
+ context.setOutputStream(new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ if (b == 255) {
+ old.write(0);
+ } else {
+ old.write(b + 1);
+ }
+ }
+ });
+ context.proceed();
+ }
+ }
+
+ /**
+ * Interceptor which adds +1 to each byte read from the stream.
+ */
+ @Provider
+ @Priority(300)
+ public static class MinusOneReaderInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final InputStream old = context.getInputStream();
+ context.setInputStream(new InputStream() {
+
+ @Override
+ public int read() throws IOException {
+ int b = old.read();
+ if (b == -1) {
+ return -1;
+ } else if (b == 0) {
+ return 255;
+ } else {
+ return b - 1;
+ }
+ }
+ });
+
+ return context.proceed();
+ }
+ }
+
+ /**
+ * Interceptor that tries to set annotations of {@link InterceptorContext} to {@code null},
+ * empty array and finally to the original value.
+ */
+ @Provider
+ @Priority(300)
+ public static class AnnotationsReaderWriterInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final Annotation[] annotations = context.getAnnotations();
+
+ // Fails if no NPE is thrown.
+ unsetAnnotations(context);
+ // Ok.
+ setAnnotations(context, new Annotation[0]);
+ // Ok.
+ setAnnotations(context, annotations);
+
+ return context.proceed();
+ }
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final Annotation[] annotations = context.getAnnotations();
+
+ // Fails if no NPE is thrown.
+ unsetAnnotations(context);
+ // Ok.
+ setAnnotations(context, new Annotation[0]);
+ // Ok.
+ setAnnotations(context, annotations);
+
+ context.proceed();
+ }
+
+ private void setAnnotations(final InterceptorContext context, final Annotation[] annotations) {
+ if (context.getAnnotations() != null) {
+ context.setAnnotations(annotations);
+ }
+ }
+
+ private void unsetAnnotations(final InterceptorContext context) {
+ try {
+ context.setAnnotations(null);
+
+ fail("NullPointerException expected.");
+ } catch (NullPointerException npe) {
+ // OK.
+ }
+ }
+ }
+
+ @Provider
+ @Priority(100)
+ public static class IOExceptionReaderInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ throw new IOException("client io");
+ }
+ }
+
+ @Test
+ public void testIOException() throws IOException {
+ client().register(IOExceptionReaderInterceptor.class);
+
+ WebTarget target = target().path("test");
+
+ Response response = target.request().put(Entity.entity(ENTITY, MediaType.TEXT_PLAIN_TYPE));
+
+ try {
+ response.readEntity(String.class);
+ fail("ProcessingException expected.");
+ } catch (ProcessingException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ }
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorGzipTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorGzipTest.java
new file mode 100644
index 0000000..96475ab
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/InterceptorGzipTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests gzip interceptors.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class InterceptorGzipTest extends JerseyTest {
+
+ private static final String FROM_RESOURCE = "-from_resource";
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(TestResource.class, GZIPWriterTestInterceptor.class,
+ GZIPReaderTestInterceptor.class); // GZIPInterceptor.class
+ }
+
+ @Test
+ public void testGzipInterceptorOnlyOnServer() throws IOException {
+ client().register(GZIPWriterTestInterceptor.class);
+ WebTarget target = target().path("test");
+ String entity = "hello, this is text entity";
+ Response response = target.request().put(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE));
+ InputStream is = response.readEntity(InputStream.class);
+ GZIPInputStream gzipIs = new GZIPInputStream(is);
+ BufferedReader br = new BufferedReader(new InputStreamReader(gzipIs));
+ String str = br.readLine();
+ assertEquals(entity + FROM_RESOURCE, str);
+ }
+
+ @Test
+ public void testGzipInterceptorOnServerandClient() throws IOException {
+ client().register(GZIPReaderTestInterceptor.class).register(GZIPWriterTestInterceptor.class);
+ WebTarget target = target().path("test");
+ String entity = "hello, this is text entity";
+ Response response = target.request().put(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE));
+ String str = response.readEntity(String.class);
+ assertEquals(entity + FROM_RESOURCE, str);
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @PUT
+ @Produces("text/plain")
+ @Consumes("text/plain")
+ public String put(String str) {
+ System.out.println("resource: " + str);
+ return str + FROM_RESOURCE;
+ }
+ }
+
+ @Provider
+ @Priority(200)
+ public static class CustomWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final OutputStream old = context.getOutputStream();
+ OutputStream newOut = new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ if (b == Byte.MAX_VALUE) {
+ old.write(Byte.MIN_VALUE);
+ } else {
+ old.write(b + 1);
+ }
+ }
+ };
+ context.setOutputStream(newOut);
+ try {
+ context.proceed();
+ } finally {
+ context.setOutputStream(old);
+ }
+ }
+ }
+
+ @Provider
+ @Priority(200)
+ public static class GZIPWriterTestInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ OutputStream old = context.getOutputStream();
+ GZIPOutputStream newStream = new GZIPOutputStream(old);
+ context.setOutputStream(newStream);
+ if (context.getHeaders().containsKey(HttpHeaders.CONTENT_LENGTH)) {
+ List<Object> clen = new ArrayList<>();
+ clen.add(-1L);
+ context.getHeaders().put(HttpHeaders.CONTENT_LENGTH, clen);
+ }
+ try {
+ context.proceed();
+ } finally {
+ newStream.finish();
+ context.setOutputStream(old);
+ }
+ }
+ }
+
+ @Provider
+ @Priority(200)
+ public static class GZIPReaderTestInterceptor implements ReaderInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ InputStream old = context.getInputStream();
+ context.setInputStream(new GZIPInputStream(old));
+ try {
+ return context.proceed();
+ } finally {
+ context.setInputStream(old);
+ }
+ }
+
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/LinkTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/LinkTest.java
new file mode 100644
index 0000000..e7033ed
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/LinkTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.uri.UriTemplate;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Martin Matula
+ */
+public class LinkTest extends JerseyTest {
+
+ @Path("resource")
+ public static class Resource {
+
+ @POST
+ @Produces({
+ MediaType.APPLICATION_XHTML_XML,
+ MediaType.APPLICATION_ATOM_XML,
+ MediaType.APPLICATION_SVG_XML
+ })
+ @Path("producesxml")
+ public String producesXml() {
+ return "";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, LinkTestResource.class);
+ }
+
+ @Test
+ public void testEquals() {
+ Link link = Link.fromMethod(Resource.class, "producesXml").build();
+ String string = link.toString();
+ Link fromValueOf = Link.valueOf(string);
+ assertEquals(link, fromValueOf);
+ }
+
+ @Test
+ public void testFromResourceMethod() {
+ Link link = Link.fromMethod(Resource.class, "producesXml").build();
+ assertEquals("producesxml", link.getUri().toString());
+ }
+
+ @Test
+ public void testDelimiters() {
+ Link.Builder builder = Link.fromUri("http://localhost:80");
+ final String value = "param1value1 param1value2";
+ builder = builder.param("param1", value);
+ Link link = builder.build();
+ final Map<String, String> params = link.getParams();
+ assertEquals(value, params.get("param1"));
+ }
+
+ @Path("linktest")
+ public static class LinkTestResource {
+
+ @GET
+ public Response get(@Context UriInfo uriInfo) throws Exception {
+ URI test1 = URI.create(uriInfo.getAbsolutePath().toString() + "test1");
+ URI test2 = URI.create(uriInfo.getAbsolutePath().toString() + "test2");
+
+ return Response.ok()
+ .link("http://oracle.com", "parent")
+ .link(new URI("http://jersey.java.net"), "framework")
+ .links(
+ Link.fromUri(uriInfo.relativize(test1)).rel("test1").build(),
+ Link.fromUri(test2).rel("test2").build(),
+ Link.fromUri(uriInfo.relativize(URI.create("linktest/test3"))).rel("test3").build()
+ ).build();
+ }
+ }
+
+ @Test
+ public void simpleLinkTest() {
+ final WebTarget target = target("/linktest/");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+
+ final URI targetUri = target.getUri();
+ assertThat(response.getLink("parent").getUri(), equalTo(URI.create("http://oracle.com")));
+ assertThat(response.getLink("framework").getUri(), equalTo(URI.create("http://jersey.java.net")));
+
+ assertThat(response.getLink("test1").getUri(), equalTo(UriTemplate.resolve(targetUri, "test1")));
+ assertThat(response.getLink("test2").getUri(), equalTo(UriTemplate.resolve(targetUri, "test2")));
+ assertThat(response.getLink("test3").getUri(), equalTo(UriTemplate.resolve(targetUri, "test3")));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/MessageBodyExceptionWrappingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/MessageBodyExceptionWrappingTest.java
new file mode 100644
index 0000000..2b5d2e6
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/MessageBodyExceptionWrappingTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import static javax.ws.rs.client.Entity.entity;
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class MessageBodyExceptionWrappingTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ /**
+ * Tests whether fail of message body writer causes throwing exception. Previously the
+ * exception was not thrown and 500 status code was returned in the response.
+ */
+ @Test
+ public void testWrapping() {
+ WebTarget resource = target().path("test");
+ StreamSource source = new StreamSource() {
+ @Override
+ public InputStream getInputStream() {
+ throw new WebApplicationException(555);
+ }
+ };
+ try {
+ Response response = resource.request().post(Entity.entity(source, MediaType.TEXT_XML_TYPE));
+ fail("Exception expected, instead response with " + response.getStatus() + " status has been returned.");
+ } catch (ProcessingException e) {
+ assertEquals(WebApplicationException.class, e.getCause().getClass());
+ assertEquals(555, ((WebApplicationException) e.getCause()).getResponse().getStatus());
+ }
+ }
+
+ @Path("test")
+ public static class TestResource {
+
+ @POST
+ public String echo(String entity) {
+ return entity;
+ }
+ }
+
+ /**
+ * Provider reproducing JERSEY-1990.
+ */
+ @Produces("text/foo")
+ public static class ThrowingUpProvider implements MessageBodyWriter<String>, MessageBodyReader<String> {
+ public volatile int counter = 0;
+
+ public int getInvocationCount() {
+ return counter;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ counter++;
+ final RuntimeException up = new RuntimeException("lunch");
+ throw up;
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ throw new UnsupportedOperationException("This method should not have ever been called.");
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ counter++;
+ final RuntimeException up = new RuntimeException("dinner");
+ throw up;
+ }
+
+ @Override
+ public String readFrom(Class<String> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ throw new UnsupportedOperationException("This method should not have ever been called.");
+ }
+ }
+
+ /**
+ * Reproducer for JERSEY-1990.
+ */
+ @Test
+ public void testMbwHandlingExceptionInIsReadableWritable() {
+ ThrowingUpProvider throwingUpProvider = new ThrowingUpProvider();
+
+ final String response =
+ target("test").register(throwingUpProvider).request("text/foo").post(entity("hello", "text/foo"), String.class);
+
+ assertEquals("hello", response);
+ assertEquals(2, throwingUpProvider.getInvocationCount());
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HugeEntityTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HugeEntityTest.java
new file mode 100644
index 0000000..3f6e0a4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HugeEntityTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test to make sure huge entity gets chunk-encoded.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class HugeEntityTest extends JerseyTest {
+
+ private static final int BUFFER_LENGTH = 1024 * 1024; // 1M
+ private static final long HUGE_DATA_LENGTH = 20L * 1024L * 1024L * 1024L; // 20G seems sufficient
+
+ /**
+ * JERSEY-2337 reproducer. The resource is used to check the right amount of data
+ * is being received from the client and also gives us ability to check we receive
+ * correct data.
+ */
+ @Path("/")
+ public static class ConsumerResource {
+
+ /**
+ * Return back the count of bytes received.
+ * This way, we should be able to consume a huge amount of data.
+ */
+ @POST
+ @Path("size")
+ public String post(InputStream in) throws IOException {
+
+ long totalBytesRead = 0L;
+
+ byte[] buffer = new byte[BUFFER_LENGTH];
+ int read;
+ do {
+ read = in.read(buffer);
+ if (read > 0) {
+ totalBytesRead += read;
+ }
+ } while (read != -1);
+
+ return String.valueOf(totalBytesRead);
+ }
+
+ @POST
+ @Path("echo")
+ public String echo(String s) {
+ return s;
+ }
+ }
+
+ private final ConnectorProvider connectorProvider;
+
+ public HugeEntityTest(ConnectorProvider connectorProvider) {
+ this.connectorProvider = connectorProvider;
+ }
+
+ @Parameterized.Parameters
+ public static List<? extends ConnectorProvider> testData() {
+ return Arrays.asList(new GrizzlyConnectorProvider(), new JdkConnectorProvider());
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ConsumerResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(TestEntityWriter.class);
+ config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+ config.connectorProvider(connectorProvider);
+ }
+
+ public static class TestEntity {
+
+ final long size;
+
+ public TestEntity(long size) {
+ this.size = size;
+ }
+ }
+
+ /**
+ * Utility writer that generates that many zero bytes as given by the input entity size field.
+ */
+ public static class TestEntityWriter implements MessageBodyWriter<TestEntity> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == TestEntity.class;
+ }
+
+ @Override
+ public long getSize(TestEntity t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1; // no matter what we return here, the output will get chunk-encoded
+ }
+
+ @Override
+ public void writeTo(TestEntity t,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+
+ final byte[] buffer = new byte[BUFFER_LENGTH];
+ final long bufferCount = t.size / BUFFER_LENGTH;
+ final int remainder = (int) (t.size % BUFFER_LENGTH);
+
+ for (long b = 0; b < bufferCount; b++) {
+ entityStream.write(buffer);
+ }
+
+ if (remainder > 0) {
+ entityStream.write(buffer, 0, remainder);
+ }
+ }
+ }
+
+ /**
+ * JERSEY-2337 reproducer. We are going to send huge amount of data over the wire.
+ * Should not the data have been chunk-encoded, we would easily run out of memory.
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testPost() throws Exception {
+ Response response = target("/size").request()
+ .post(Entity.entity(new TestEntity(HUGE_DATA_LENGTH), MediaType.APPLICATION_OCTET_STREAM_TYPE));
+ String content = response.readEntity(String.class);
+ assertThat(Long.parseLong(content), equalTo(HUGE_DATA_LENGTH));
+
+ // just to check the right data have been transfered.
+ response = target("/echo").request().post(Entity.text("Hey Sync!"));
+ assertThat(response.readEntity(String.class), equalTo("Hey Sync!"));
+ }
+
+ /**
+ * JERSEY-2337 reproducer. We are going to send huge amount of data over the wire. This time in an async fashion.
+ * Should not the data have been chunk-encoded, we would easily run out of memory.
+ *
+ * @throws Exception in case of a test error.
+ */
+ @Test
+ public void testAsyncPost() throws Exception {
+ Future<Response> response = target("/size").request().async()
+ .post(Entity.entity(new TestEntity(HUGE_DATA_LENGTH), MediaType.APPLICATION_OCTET_STREAM_TYPE));
+ final String content = response.get().readEntity(String.class);
+ assertThat(Long.parseLong(content), equalTo(HUGE_DATA_LENGTH));
+
+ // just to check the right data have been transfered.
+ response = target("/echo").request().async().post(Entity.text("Hey Async!"));
+ assertThat(response.get().readEntity(String.class), equalTo("Hey Async!"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MethodTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MethodTest.java
new file mode 100644
index 0000000..c3d2d0e
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MethodTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client.connector;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the Http methods.
+ *
+ * @author Stepan Kopriva
+ */
+@RunWith(Parameterized.class)
+public class MethodTest extends JerseyTest {
+
+ private static final String PATH = "test";
+
+ @Path("/test")
+ public static class HttpMethodResource {
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @POST
+ public String post(String entity) {
+ return entity;
+ }
+
+ @PUT
+ public String put(String entity) {
+ return entity;
+ }
+
+ @DELETE
+ public String delete() {
+ return "DELETE";
+ }
+ }
+
+ private final ConnectorProvider connectorProvider;
+
+ public MethodTest(ConnectorProvider connectorProvider) {
+ this.connectorProvider = connectorProvider;
+ }
+
+ @Parameterized.Parameters
+ public static List<? extends ConnectorProvider> testData() {
+ return Arrays.asList(new GrizzlyConnectorProvider(), new JdkConnectorProvider());
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HttpMethodResource.class);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(connectorProvider);
+ }
+
+ @Test
+ public void testGet() {
+ Response response = target(PATH).request().get();
+ assertEquals("GET", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPost() {
+ Response response = target(PATH).request().post(Entity.entity("POST", MediaType.TEXT_PLAIN));
+ assertEquals("POST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testPut() {
+ Response response = target(PATH).request().put(Entity.entity("PUT", MediaType.TEXT_PLAIN));
+ assertEquals("PUT", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testDelete() {
+ Response response = target(PATH).request().delete();
+ assertEquals("DELETE", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/AutoDiscoverableTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/AutoDiscoverableTest.java
new file mode 100644
index 0000000..5c0b7c3
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/AutoDiscoverableTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Note: Auto-discoverables from this test "affects" all other tests in suit.
+ *
+ * @author Michal Gajdos
+ */
+public class AutoDiscoverableTest extends JerseyTest {
+
+ private static final String PROPERTY = "AutoDiscoverableTest";
+
+ public static class CommonAutoDiscoverable implements AutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-common");
+
+ context.proceed();
+ }
+ }, 1);
+ }
+ }
+
+ @ConstrainedTo(RuntimeType.CLIENT)
+ public static class ClientAutoDiscoverable implements AutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-client");
+
+ context.proceed();
+ }
+ }, 10);
+ }
+ }
+
+ @ConstrainedTo(RuntimeType.SERVER)
+ public static class ServerAutoDiscoverable implements AutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-server");
+
+ context.proceed();
+ }
+ }, 10);
+ }
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ public String post(final String value) {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class).property(PROPERTY, true);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.property(PROPERTY, true);
+ }
+
+ @Test
+ public void testAutoDiscoverableConstrainedTo() throws Exception {
+ final Response response = target().request().post(Entity.text("value"));
+
+ assertEquals("value-common-client-common-server", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ConstrainedToTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ConstrainedToTest.java
new file mode 100644
index 0000000..79bbc5f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ConstrainedToTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests whether providers are correctly validated in the client runtime (for example if provider constrained to
+ * server runtime is skipped in the client).
+
+ * @author Miroslav Fuksa
+ *
+ */
+public class ConstrainedToTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testClientWithProviderClasses() {
+ Client client = ClientBuilder.newClient(new ClientConfig(ClientFilterConstrainedToServer.class,
+ ClientFilterConstrainedToClient.class, ClientFilter.class));
+
+ _testFilters(client);
+ }
+
+ @Test
+ public void testClientWithProviderInstances() {
+ Client client = ClientBuilder.newClient(new ClientConfig(new ClientFilterConstrainedToServer(),
+ new ClientFilterConstrainedToClient(), new ClientFilter()));
+
+ _testFilters(client);
+ }
+
+ private void _testFilters(Client client) {
+ final Response response = client.target(getBaseUri()).path("resource").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("called", response.getHeaderString("ClientFilterConstrainedToClient"));
+ Assert.assertEquals("called", response.getHeaderString("ClientFilter"));
+ Assert.assertNull("The ClientFilterConstrainedToServer should not be called as it is constrained to server.",
+ response.getHeaderString("ClientFilterConstrainedToServer"));
+ }
+
+ @ConstrainedTo(RuntimeType.CLIENT)
+ public static class ClientFilterConstrainedToClient implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().add("ClientFilterConstrainedToClient", "called");
+ }
+ }
+
+ public static class ClientFilter implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().add("ClientFilter", "called");
+ }
+ }
+
+ /**
+ * Wrong configuration of Client filter which is constrained to server. This filter will be never called.
+ */
+ @ConstrainedTo(RuntimeType.SERVER)
+ public static class ClientFilterConstrainedToServer implements ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().add("ClientFilterConstrainedToServer", "called");
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+ @GET
+ public String get() {
+ return "get";
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentLengthTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentLengthTest.java
new file mode 100644
index 0000000..6e8785f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentLengthTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ContentLengthTest extends JerseyTest {
+
+ public static String STR = "string";
+
+ @Override
+ protected Application configure() {
+ ResourceConfig rc = new ResourceConfig();
+ rc.registerClasses(MyTypeResource.class, MyTypeWriter.class, ResourceGetByteNoHead.class);
+ return rc;
+ }
+
+ public static class MyType {
+
+ public String s = STR;
+ }
+
+ @Path("/")
+ public static class MyTypeResource {
+
+ @GET
+ public MyType getMyType() {
+ return new MyType();
+ }
+ }
+
+ @Provider
+ public static class MyTypeWriter implements MessageBodyWriter<MyType> {
+
+ @Override
+ public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
+ return aClass.equals(MyType.class);
+ }
+
+ @Override
+ public long getSize(MyType myType, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
+ return myType.s.length();
+ }
+
+ @Override
+ public void writeTo(MyType myType,
+ Class<?> aClass,
+ Type type,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> stringObjectMultivaluedMap,
+ OutputStream outputStream) throws IOException, WebApplicationException {
+ outputStream.write(myType.s.getBytes());
+ }
+ }
+
+ @Test
+ public void testGetContentLengthCustomWriter() throws Exception {
+ Response response = target().request().get(Response.class);
+ assertEquals(200, response.getStatus());
+ assertEquals(STR.length(), Integer.parseInt(response.getHeaderString(HttpHeaders.CONTENT_LENGTH)));
+ assertTrue(response.hasEntity());
+ }
+
+ @Test
+ public void testHeadContentLengthCustomWriter() throws Exception {
+ Response response = target().request().head();
+ assertEquals(200, response.getStatus());
+ assertEquals(STR.length(), Integer.parseInt(response.getHeaderString(HttpHeaders.CONTENT_LENGTH)));
+ assertFalse(response.hasEntity());
+ }
+
+ @Path("/byte")
+ public static class ResourceGetByteNoHead {
+
+ @GET
+ public byte[] get() {
+ return "GET".getBytes();
+ }
+ }
+
+ @Test
+ public void testGetByte() throws Exception {
+ Response response = target().path("byte").request().get(Response.class);
+ assertEquals(200, response.getStatus());
+ assertEquals(3, Integer.parseInt(response.getHeaderString(HttpHeaders.CONTENT_LENGTH)));
+ assertTrue(response.hasEntity());
+ }
+
+ @Test
+ public void testHeadByte() throws Exception {
+ Response response = target().path("byte").request().head();
+ assertEquals(200, response.getStatus());
+ assertEquals(3, Integer.parseInt(response.getHeaderString(HttpHeaders.CONTENT_LENGTH)));
+ assertFalse(response.hasEntity());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentTypeTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentTypeTest.java
new file mode 100644
index 0000000..ad65f33
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ContentTypeTest.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.logging.Logger;
+
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ContentTypeTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(ContentTypeTest.class.getName());
+
+ @Path(value = "/ContentType")
+ public static class ContentTypeResource {
+
+ @POST
+ @Produces("text/plain")
+ @SuppressWarnings("UnusedParameters")
+ public void postTest(final String str) {
+ // Ignore to generate response 204 - NoContent.
+ }
+
+ @POST
+ @Path("changeTest")
+ @Produces("foo/bar")
+ @CtFix(ContainerRequestFilter.class)
+ public String changeContentTypeTest(String echo) {
+ return echo;
+ }
+
+ @POST
+ @Path("null-content")
+ public String process(@HeaderParam(HttpHeaders.CONTENT_TYPE) String mediaType, @Context ContainerRequest request) {
+ return mediaType + "-" + request.hasEntity();
+ }
+
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ @interface CtFix {
+
+ Class<? super ContentTypeFixProvider> value();
+ }
+
+ public static class ContentTypeFixProvider
+ implements ReaderInterceptor, ContainerRequestFilter, ClientResponseFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ System.out.println("filter1");
+ if (responseContext.getMediaType().toString().equals("foo/bar")) {
+ responseContext.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext context) throws IOException {
+ System.out.println("filter2");
+ if (context.getMediaType().toString().equals("foo/bar")) {
+ context.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+ }
+ }
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ System.out.println("reader");
+ if (context.getMediaType().toString().equals("foo/bar")) {
+ context.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+ }
+
+ return context.proceed();
+ }
+ }
+
+ public static class ContentTypeFixFeature implements DynamicFeature {
+
+ @Override
+ public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+ final CtFix annotation = resourceInfo.getResourceMethod().getAnnotation(CtFix.class);
+ if (annotation != null) {
+ context.register(ContentTypeFixProvider.class, annotation.value());
+ }
+ }
+ }
+
+ @Produces("foo/bar")
+ public static class FooBarStringWriter implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == String.class && mediaType.toString().equals("foo/bar");
+ }
+
+ @Override
+ public long getSize(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return s.length();
+ }
+
+ @Override
+ public void writeTo(String s,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+
+ entityStream.write(s.getBytes());
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.DUMP_ENTITY);
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig()
+ .registerClasses(ContentTypeResource.class, ContentTypeFixFeature.class, FooBarStringWriter.class)
+ .registerInstances(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ @Test
+ public void testContentTypeHeaderForNoContentResponse() {
+ final Response response = target().path("ContentType").request().post(Entity.entity("", MediaType.TEXT_PLAIN_TYPE));
+
+ assertEquals(204, response.getStatus());
+ assertNull(response.getHeaderString("Content-Type"));
+ }
+
+ @Test
+ public void testInvalidContentTypeHeader() throws Exception {
+ final URL url = new URL(getBaseUri().toString() + "ContentType");
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.setRequestProperty("Content-Type", "^^^");
+
+ connection.setDoOutput(true);
+ connection.connect();
+
+ final OutputStream outputStream = connection.getOutputStream();
+ outputStream.write("HelloWorld!".getBytes());
+ outputStream.write('\n');
+ outputStream.flush();
+
+ assertEquals(400, connection.getResponseCode());
+ }
+
+ @Test
+ public void testChangeContentTypeHeader() throws Exception {
+ WebTarget target;
+ Response response;
+
+ // filter test
+ target = target().path("ContentType").path("changeTest");
+ target.register(ContentTypeFixProvider.class, ClientResponseFilter.class)
+ .register(FooBarStringWriter.class);
+
+ response = target
+ .request().post(Entity.entity("test", "foo/bar"));
+
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+ assertEquals("test", response.readEntity(String.class));
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+
+ // interceptor test
+ target = target().path("ContentType").path("changeTest");
+ target.register(ContentTypeFixProvider.class, ReaderInterceptor.class)
+ .register(FooBarStringWriter.class);
+
+ response = target
+ .request().post(Entity.entity("test", "foo/bar"));
+
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.valueOf("foo/bar"), response.getMediaType());
+ assertEquals("test", response.readEntity(String.class));
+ assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+ }
+
+ @Test
+ public void testEmptyPostRequestWithContentType() {
+ String response = target().path("ContentType/null-content").request("text/plain")
+ .post(Entity.entity(null, "foo/bar"), String.class);
+
+ assertEquals("foo/bar-false", response);
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/DetermineContentLengthTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/DetermineContentLengthTest.java
new file mode 100644
index 0000000..05cab0a
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/DetermineContentLengthTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test determining of the content length.
+ *
+ * @author Miroslav Fuksa
+ */
+public class DetermineContentLengthTest extends JerseyTest {
+
+ public static final int BUFFER_SIZE = 20;
+
+ public static final String STR0 = "";
+ public static final String STR6 = "123456";
+ public static final String STR12 = "123456789ABC";
+
+ @Path("root")
+ public static class Resource {
+
+ @GET
+ @Path("6")
+ @Produces("text/plain")
+ public String get6() {
+ return STR6;
+ }
+
+
+ @GET
+ @Path("0")
+ @Produces("text/plain")
+ public String get0() {
+ return STR0;
+ }
+
+
+ @GET
+ @Produces("text/plain")
+ @Path("12")
+ public String get5() {
+ return STR12;
+ }
+
+ @Path("test")
+ @POST
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public String testLength(String entity, @DefaultValue("-1") @HeaderParam(HttpHeaders.CONTENT_LENGTH) String length) {
+ return length;
+ }
+ }
+
+ @Priority(300)
+ public static class DoubleInterceptor implements WriterInterceptor, ReaderInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final OutputStream old = context.getOutputStream();
+ context.setOutputStream(new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ old.write(b);
+ old.write(b);
+ }
+ });
+ context.proceed();
+ context.setOutputStream(old);
+ }
+
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ final InputStream old = context.getInputStream();
+ try {
+ context.setInputStream(new InputStream() {
+
+ @Override
+ public int read() throws IOException {
+ old.read();
+ return old.read();
+ }
+ });
+
+ return context.proceed();
+ } finally {
+ context.setInputStream(old);
+ }
+
+ }
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new InMemoryTestContainerFactory();
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(Resource.class, DoubleInterceptor.class);
+ resourceConfig.property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, BUFFER_SIZE);
+ return resourceConfig;
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, BUFFER_SIZE);
+ config.register(DoubleInterceptor.class);
+ }
+
+ @Test
+ public void test0() {
+ final Response response = target().path("root/0").request().get();
+ assertEquals(200, response.getStatus());
+ final Object headerContentLength = Integer.valueOf(response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ assertEquals(STR0.length() * 2, headerContentLength);
+ assertEquals(STR0, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testHead0() {
+ final Response response = target().path("root/0").request().head();
+ assertEquals(200, response.getStatus());
+ final Object headerContentLength = Integer.valueOf(response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ assertEquals(STR0.length() * 2, headerContentLength);
+ }
+
+ @Test
+ public void test6() {
+ final Response response = target().path("root/6").request().get();
+ assertEquals(200, response.getStatus());
+ final Object headerContentLength = Integer.valueOf(response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ assertEquals(STR6.length() * 2, headerContentLength);
+ assertEquals(STR6, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testHead6() {
+ final Response response = target().path("root/6").request().head();
+ assertEquals(200, response.getStatus());
+ final Object headerContentLength = Integer.valueOf(response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ assertEquals(STR6.length() * 2, headerContentLength);
+ }
+
+ @Test
+ public void test12() {
+ final Response response = target().path("root/12").request().get();
+ assertEquals(200, response.getStatus());
+ checkEmptyContentLength(response);
+ assertEquals(STR12, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testHead12() {
+ final Response response = target().path("root/12").request().head();
+ assertEquals(200, response.getStatus());
+ checkEmptyContentLength(response);
+ }
+
+ private void checkEmptyContentLength(Response response) {
+ final String headerString = response.getHeaderString(HttpHeaders.CONTENT_LENGTH);
+ if (headerString != null) {
+ final Object headerContentLength = Integer.valueOf(headerString);
+ assertEquals(-1, headerContentLength);
+ }
+ }
+
+ @Test
+ public void testClientLength0() {
+ final Response response = target().path("root/test").request().post(Entity.entity(STR0, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(STR0.length() * 2, response.readEntity(Integer.class).intValue());
+ }
+
+ @Test
+ public void testClientLength6() {
+ final Response response = target().path("root/test").request().post(Entity.entity(STR6, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(STR6.length() * 2, response.readEntity(Integer.class).intValue());
+ }
+
+ @Test
+ public void testClientLength12() {
+ final Response response = target().path("root/test").request().post(Entity.entity(STR12, MediaType.TEXT_PLAIN_TYPE));
+ assertEquals(200, response.getStatus());
+ assertEquals(-1, response.readEntity(Integer.class).intValue());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/EncodingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/EncodingTest.java
new file mode 100644
index 0000000..2e4ce8c
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/EncodingTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.filter.EncodingFilter;
+import org.glassfish.jersey.message.DeflateEncoder;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class EncodingTest extends JerseyTest {
+ @Path("/")
+ public static class EchoResource {
+ @POST
+ public String post(String text) {
+ return text;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(
+ EchoResource.class,
+ org.glassfish.jersey.server.filter.EncodingFilter.class,
+ GZipEncoder.class,
+ DeflateEncoder.class
+ );
+ }
+
+ @Test
+ public void testGZip() throws IOException {
+ test(new TestSpec() {
+ @Override
+ public InputStream decode(InputStream stream) throws IOException {
+ return new GZIPInputStream(stream);
+ }
+
+ @Override
+ public void checkHeadersAndStatus(Response response) {
+ assertEquals("gzip", response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
+ }
+
+ @Override
+ public Invocation.Builder setHeaders(Invocation.Builder invBuilder) {
+ return invBuilder.header(HttpHeaders.ACCEPT_ENCODING, "gzip");
+ }
+ });
+ }
+
+ @Test
+ public void testDeflate() throws IOException {
+ test(new TestSpec() {
+ @Override
+ public InputStream decode(InputStream stream) throws IOException {
+ return new InflaterInputStream(stream);
+ }
+
+ @Override
+ public void checkHeadersAndStatus(Response response) {
+ assertEquals("deflate", response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
+ }
+
+ @Override
+ public Invocation.Builder setHeaders(Invocation.Builder invBuilder) {
+ return invBuilder.header(HttpHeaders.ACCEPT_ENCODING, "deflate");
+ }
+ });
+ }
+
+ @Test
+ public void testGZipPreferred() throws IOException {
+ test(new TestSpec() {
+ @Override
+ public InputStream decode(InputStream stream) throws IOException {
+ return new GZIPInputStream(stream);
+ }
+
+ @Override
+ public void checkHeadersAndStatus(Response response) {
+ assertEquals("x-gzip", response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
+ }
+
+ @Override
+ public Invocation.Builder setHeaders(Invocation.Builder invBuilder) {
+ return invBuilder.header(HttpHeaders.ACCEPT_ENCODING, "deflate; q=.5, x-gzip");
+ }
+ });
+ }
+
+ @Test
+ public void testGZipClientServer() throws IOException {
+ test(new TestSpec() {
+ @Override
+ public WebTarget configure(WebTarget target) {
+ target.register(GZipEncoder.class).register(EncodingFilter.class);
+ return target;
+ }
+
+ @Override
+ public void checkHeadersAndStatus(Response response) {
+ assertEquals("gzip", response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
+ }
+ });
+ }
+
+ @Test
+ public void testDeflatePreferredClientServer() throws IOException {
+ test(new TestSpec() {
+ @Override
+ public Invocation.Builder setHeaders(Invocation.Builder invBuilder) {
+ return invBuilder.header(HttpHeaders.ACCEPT_ENCODING, "deflate,gzip=.5");
+ }
+
+ @Override
+ public WebTarget configure(WebTarget target) {
+ target.register(DeflateEncoder.class)
+ .register(GZipEncoder.class).register(EncodingFilter.class);
+ return target;
+ }
+
+ @Override
+ public void checkHeadersAndStatus(Response response) {
+ assertEquals("deflate", response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
+ }
+ });
+ }
+
+ private void test(TestSpec testSpec) throws IOException {
+ String input = "hello";
+ Response response = testSpec.setHeaders(testSpec.configure(target()).request())
+ .post(Entity.text(input));
+ byte[] output = response.readEntity(byte[].class);
+ testSpec.checkHeadersAndStatus(response);
+ InputStream decoded = testSpec.decode(new ByteArrayInputStream(output));
+ byte[] result = new byte[input.getBytes().length];
+ int len = decoded.read(result);
+ assertEquals(-1, decoded.read());
+ decoded.close();
+ assertEquals(input.getBytes().length, len);
+ assertArrayEquals(input.getBytes(), result);
+ }
+
+ private static class TestSpec {
+ public InputStream decode(InputStream stream) throws IOException {
+ return stream;
+ }
+
+ public Invocation.Builder setHeaders(Invocation.Builder invBuilder) {
+ return invBuilder;
+ }
+
+ public WebTarget configure(WebTarget target) {
+ return target;
+ }
+
+ public void checkHeadersAndStatus(Response response) {
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ForcedAutoDiscoverableTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ForcedAutoDiscoverableTest.java
new file mode 100644
index 0000000..7defa2d
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ForcedAutoDiscoverableTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Note: Auto-discoverables from this test "affects" all other tests in suit.
+ *
+ * @author Michal Gajdos
+ */
+public class ForcedAutoDiscoverableTest extends JerseyTest {
+
+ private static final String PROPERTY = "ForcedAutoDiscoverableTest";
+
+ public static class CommonAutoDiscoverable implements ForcedAutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-common");
+
+ context.proceed();
+ }
+ }, 1);
+ }
+ }
+
+ @ConstrainedTo(RuntimeType.CLIENT)
+ public static class ClientAutoDiscoverable implements ForcedAutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-client");
+
+ context.proceed();
+ }
+ }, 10);
+ }
+ }
+
+ @ConstrainedTo(RuntimeType.SERVER)
+ public static class ServerAutoDiscoverable implements ForcedAutoDiscoverable {
+
+ @Override
+ public void configure(final FeatureContext context) {
+ // Return if PROPERTY is not true - applicable for other tests.
+ if (!PropertiesHelper.isProperty(context.getConfiguration().getProperty(PROPERTY))) {
+ return;
+ }
+
+ context.register(new WriterInterceptor() {
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-server");
+
+ context.proceed();
+ }
+ }, 10);
+ }
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ public String post(final String value) {
+ return value;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class)
+ .property(PROPERTY, true)
+ .property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE_SERVER, true)
+ .property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_SERVER, true);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.property(PROPERTY, true)
+ .property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT, true)
+ .property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE_CLIENT, true);
+ }
+
+ @Test
+ public void testForcedAutoDiscoverable() throws Exception {
+ final Response response = target().request().post(Entity.text("value"));
+
+ assertThat(response.readEntity(String.class), is("value-common-client-common-server"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderParamTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderParamTest.java
new file mode 100644
index 0000000..0a328f4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderParamTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class HeaderParamTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MyResource.class, LoggingFeature.class);
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @GET
+ public String get(@HeaderParam("hello") List<String> headers) {
+ return headers.size() + ":" + headers;
+ }
+ }
+
+ @Test
+ public void testHeaderListSingleHeader() throws Exception {
+ Response response = target().path("resource").request().header("hello", "world").header("hello", "universe").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("1:[world,universe]"));
+ }
+
+ /**
+ * Check that multi value http headers are correctly read by the server.
+ */
+ @Test
+ public void testHeaderListMultipleHeaders() throws Exception {
+ final URL url = new URL(getBaseUri().toString() + "resource");
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.setRequestProperty("hello", "world");
+ connection.addRequestProperty("hello", "universe");
+
+ connection.setDoOutput(false);
+ connection.connect();
+
+ assertThat(connection.getResponseCode(), equalTo(200));
+ assertThat(ReaderWriter.readFromAsString(new InputStreamReader(connection.getInputStream())),
+ equalTo("2:[world, universe]"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderValueExceptionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderValueExceptionTest.java
new file mode 100644
index 0000000..97f5305
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/HeaderValueExceptionTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests HeaderValueException.
+ *
+ * @author Miroslav Fuksa
+ */
+public class HeaderValueExceptionTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ResponseFilter.class, TestResource.class);
+ }
+
+ @Test
+ public void testInboundHeaderThrowsException() throws ExecutionException, InterruptedException {
+ final Response response = target("resource/inbound").request()
+ .header(HttpHeaders.DATE, "foo")
+ .post(Entity.entity("inbound", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(400, response.getStatus());
+ }
+
+ @Test
+ public void testOutboundHeaderThrowsException() throws ExecutionException, InterruptedException {
+ final Response response = target("resource/outbound").request()
+ .post(Entity.entity("outbound", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testOutboundResponseHeaderThrowsException() throws ExecutionException, InterruptedException {
+ final Response response = target("resource/outbound-Response").request()
+ .post(Entity.entity("outbound", MediaType.TEXT_PLAIN_TYPE));
+ Assert.assertEquals(500, response.getStatus());
+ }
+
+
+ public static class ResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ // this call should throw HeaderValueException which will be converted to HTTP 500 response
+ responseContext.getDate();
+ }
+ }
+
+ @Path("resource")
+ public static class TestResource {
+ @POST
+ @Path("inbound")
+ public String postInbound(String entity, @Context HttpHeaders headers) {
+ // this call should throw HeaderValueException which will be converted to HTTP 400 response
+ headers.getDate();
+ return entity;
+ }
+
+ @POST
+ @Path("outbound")
+ public Response postOutbound(String entity) {
+ return Response.ok().entity(entity).header(HttpHeaders.DATE, "bar").build();
+ }
+
+ @POST
+ @Path("outbound-Response")
+ public Response postOutboundResponse(String entity) {
+ final Response response = Response.ok(entity).header(HttpHeaders.DATE, "foo").build();
+ // this call should throw HeaderValueException which will be converted to HTTP 500 response
+ response.getDate();
+ return response;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/Hk2BinderSupportTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/Hk2BinderSupportTest.java
new file mode 100644
index 0000000..7ecb616
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/Hk2BinderSupportTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that HK2Binder and Jersey Binder work together.
+ *
+ * @author Petr Bouda
+ */
+public class Hk2BinderSupportTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ ResourceConfig config = new ResourceConfig();
+ config.register(HelloWorldResource.class);
+ config.register(new Hk2Binder());
+ config.register(new JerseyBinder());
+ return config;
+ }
+
+ @Test
+ public void testResponse() {
+ String s = target().path("helloworld").request().get(String.class);
+ assertEquals(Hk2Binder.HK2_HELLO_MESSAGE + "/" + JerseyBinder.JERSEY_HELLO_MESSAGE, s);
+ }
+
+ private static class Hk2Binder extends AbstractBinder {
+ private static final String HK2_HELLO_MESSAGE = "Hello HK2!";
+
+ @Override
+ protected void configure() {
+ bind(HK2_HELLO_MESSAGE).to(String.class).named("hk2");
+ }
+ }
+
+ private static class JerseyBinder extends org.glassfish.jersey.internal.inject.AbstractBinder {
+ private static final String JERSEY_HELLO_MESSAGE = "Hello Jersey!";
+
+ @Override
+ protected void configure() {
+ bind(JERSEY_HELLO_MESSAGE).to(String.class).named("jersey");
+ }
+ }
+
+ @Path("helloworld")
+ public static class HelloWorldResource {
+
+ @Inject
+ @Named("hk2")
+ private String hk2Hello;
+
+ @Inject
+ @Named("jersey")
+ private String jerseyHello;
+
+ @GET
+ public String getHello() {
+ return hk2Hello + "/" + jerseyHello;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java
new file mode 100644
index 0000000..f15e5d8
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.lessThan;
+
+/**
+ * {@link LoggingFeature} end-to-end tests.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ LoggingFeatureTest.ClientTest.class,
+ LoggingFeatureTest.ContainerTest.class,
+ LoggingFeatureTest.ContainerAutodiscoveryTest.class,
+ LoggingFeatureTest.FiltersOrderTest.class
+})
+public class LoggingFeatureTest {
+
+ private static final String LOGGER_NAME = "org.glassfish.jersey.logging.feature";
+ private static final String BINARY_MEDIA_TYPE = "application/binary";
+ private static final String TEXT_MEDIA_TYPE = MediaType.TEXT_PLAIN;
+ private static final String ENTITY = "This entity must (not) be logged";
+
+ @Path("/")
+ public static class MyResource {
+
+ @GET
+ @Produces(BINARY_MEDIA_TYPE)
+ public Response getHeadersAndBinaryPayload() {
+ return Response
+ .ok(ENTITY)
+ .header("001", "First Header Value")
+ .header("002", "Second Header Value")
+ .header("003", "Third Header Value")
+ .header("004", "Fourth Header Value")
+ .header("005", "Fifth Header Value")
+ .build();
+ }
+
+ @Path("/text")
+ @GET
+ @Produces(TEXT_MEDIA_TYPE)
+ public Response getHeadersAndTextPayload() {
+ return Response
+ .ok(ENTITY)
+ .header("001", "First Header Value")
+ .header("002", "Second Header Value")
+ .header("003", "Third Header Value")
+ .header("004", "Fourth Header Value")
+ .header("005", "Fifth Header Value")
+ .build();
+ }
+
+ @Path("/text")
+ @POST
+ @Produces(TEXT_MEDIA_TYPE)
+ public Response post(String text) {
+ return Response
+ .ok(ENTITY)
+ .build();
+ }
+
+ }
+
+ /**
+ * General client side tests.
+ */
+ public static class ClientTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+
+ return new ResourceConfig(MyResource.class);
+ }
+
+ @Test
+ public void testFilterAsClientRequestFilter() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME)))
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterRequestLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ }
+
+ @Test
+ public void testOrderOfHeadersOnClient() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME)))
+ .request()
+ .get();
+ assertThat(response.readEntity(String.class), equalTo(ENTITY));
+
+ final LogRecord record = getLoggingFilterResponseLogRecord(getLoggedRecords());
+ final String message = record.getMessage();
+
+ int i = 1;
+ do {
+ final String h1 = "00" + i++;
+ final String h2 = "00" + i;
+
+ final int i1 = message.indexOf(h1);
+ final int i2 = message.indexOf(h2);
+
+ assertThat("Header " + h1 + " has been logged sooner than header " + h2, i1, lessThan(i2));
+ } while (i < 5);
+ }
+
+ @Test
+ public void testVerbosityAnyPayload() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME), LoggingFeature.Verbosity.PAYLOAD_ANY))
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), containsString(ENTITY));
+ }
+
+ @Test
+ public void testVerbosityAnyPayloadSetVerbosityAsText() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME)))
+ .property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, "PAYLOAD_ANY")
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), containsString(ENTITY));
+ }
+
+ @Test
+ public void testVerbosityTextPayloadBinaryFiltered() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME), LoggingFeature.Verbosity.PAYLOAD_TEXT))
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), not(containsString(ENTITY)));
+ }
+
+ @Test
+ public void testVerbosityTextPayload() throws Exception {
+ final Response response = target("/text")
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME), LoggingFeature.Verbosity.PAYLOAD_TEXT))
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), containsString(ENTITY));
+ }
+
+ @Test
+ public void testVerbosityHeadersPayload() throws Exception {
+ final Response response = target()
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME), LoggingFeature.Verbosity.HEADERS_ONLY))
+ .request()
+ .get();
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), not(containsString(ENTITY)));
+ }
+
+ @Test
+ public void testPostedEntityLogged() throws Exception {
+ final Response response = target("/text")
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME), LoggingFeature.Verbosity.PAYLOAD_TEXT))
+ .request()
+ .post(Entity.text(ENTITY));
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(0).getMessage(), containsString(ENTITY));
+ }
+
+ }
+
+ /**
+ * General client side tests.
+ */
+ public static class ContainerTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
+
+ return new ResourceConfig(MyResource.class)
+ .register(LoggingFeature.class)
+ .property(LoggingFeature.LOGGING_FEATURE_LOGGER_NAME_SERVER, LOGGER_NAME);
+ }
+
+ @Test
+ public void testLoggingAsContainer() throws Exception {
+ // Correct response status.
+ assertThat(target().request().get().getStatus(), is(Response.Status.OK.getStatusCode()));
+
+ // Check logs for proper id.
+ assertThat(getLoggingFilterRequestLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterResponseLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ }
+
+ @Test
+ public void testLoggingAsContainerTextPayload() throws Exception {
+ // Correct response status.
+ assertThat(target("/text").request().get().getStatus(), is(Response.Status.OK.getStatusCode()));
+
+ // Check logs for proper id.
+ assertThat(getLoggingFilterRequestLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterResponseLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), containsString(ENTITY));
+ }
+
+ @Test
+ public void testLoggingAsContainerBinaryPayload() throws Exception {
+ // Correct response status.
+ assertThat(target().request().get().getStatus(), is(Response.Status.OK.getStatusCode()));
+
+ // Check logs for proper id.
+ assertThat(getLoggingFilterRequestLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterResponseLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(1).getMessage(), not(containsString(ENTITY)));
+ }
+
+ @Test
+ public void testPostedEntityLogged() throws Exception {
+ final Response response = target("/text")
+ .request()
+ .post(Entity.text(ENTITY));
+
+ // Correct response status.
+ assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
+ // Check logs for proper id.
+ assertThat(getLoggingFilterLogRecord(getLoggedRecords()).get(0).getMessage(), containsString(ENTITY));
+
+ }
+ }
+
+ /**
+ * General client side tests.
+ */
+ public static class ContainerAutodiscoveryTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.INFO.intValue());
+
+ return new ResourceConfig(MyResource.class)
+ .property(LoggingFeature.LOGGING_FEATURE_LOGGER_NAME_SERVER, LOGGER_NAME)
+ .property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, "INFO");
+ }
+
+ @Test
+ public void testFilterAsContainerFilter() throws Exception {
+ // Correct response status.
+ assertThat(target().request().get().getStatus(), is(Response.Status.OK.getStatusCode()));
+
+ // Check logs for proper id.
+ assertThat(getLoggingFilterRequestLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ assertThat(getLoggingFilterResponseLogRecord(getLoggedRecords()).getMessage(), containsString("1 *"));
+ }
+ }
+
+ private static LogRecord getLoggingFilterRequestLogRecord(final List<LogRecord> records) {
+ return getLoggingFilterLogRecord(records, true);
+ }
+
+ private static LogRecord getLoggingFilterResponseLogRecord(final List<LogRecord> records) {
+ return getLoggingFilterLogRecord(records, false);
+ }
+
+ private static LogRecord getLoggingFilterLogRecord(final List<LogRecord> records, final boolean requestQuery) {
+ for (final LogRecord record : getLoggingFilterLogRecord(records)) {
+ if (record.getMessage().contains(requestQuery ? "request" : "response")) {
+ return record;
+ }
+ }
+
+ throw new AssertionError("Unable to find proper log record.");
+ }
+
+ private static List<LogRecord> getLoggingFilterLogRecord(final List<LogRecord> records) {
+ final List<LogRecord> loggingFilterRecords = new ArrayList<>(records.size());
+
+ for (final LogRecord record : records) {
+ if (record.getLoggerName().startsWith(LOGGER_NAME)) {
+ loggingFilterRecords.add(record);
+ }
+ }
+
+ return loggingFilterRecords;
+ }
+
+ public static class FiltersOrderTest extends JerseyTest {
+
+ @Priority(1000)
+ private static class CustomFilter implements ClientRequestFilter, ClientResponseFilter,
+ ContainerRequestFilter, ContainerResponseFilter {
+
+ static final String CUSTOM_HEADER = "custom_header";
+
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().add(CUSTOM_HEADER, "client/request");
+ }
+
+ @Override
+ public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext)
+ throws IOException {
+ responseContext.getHeaders().add(CUSTOM_HEADER, "client/response");
+ }
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().add(CUSTOM_HEADER, "container/request");
+ }
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
+ throws IOException {
+ responseContext.getHeaders().add(CUSTOM_HEADER, "container/response");
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.INFO.intValue());
+
+ return new ResourceConfig(MyResource.class)
+ .property(LoggingFeature.LOGGING_FEATURE_LOGGER_NAME, LOGGER_NAME)
+ .property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL, "INFO")
+ .register(CustomFilter.class);
+ }
+
+ @Test
+ public void testFilterAsContainerFilter() throws Exception {
+ // Correct response status.
+ assertThat(target()
+ .register(CustomFilter.class)
+ .register(new LoggingFeature(Logger.getLogger(LOGGER_NAME),
+ Level.INFO,
+ LoggingFeature.Verbosity.HEADERS_ONLY,
+ 0))
+ .request().get().getStatus(), is(Response.Status.OK.getStatusCode()));
+
+ for (LogRecord record : getLoggedRecords()) {
+ System.out.println(record.getMessage());
+ }
+
+ // --- client request log entry
+ // client added header before request has sent (and logged)
+ assertThat(getLoggedRecords().get(0).getMessage(),
+ containsString("1 > custom_header: client/request\n"));
+
+
+ // --- container request log entry
+ // container receives header from client request
+ assertThat(getLoggedRecords().get(1).getMessage(),
+ containsString("1 > custom_header: client/request\n"));
+ // container has added its own header after logging filter logged message
+ assertThat(getLoggedRecords().get(1).getMessage(),
+ not(containsString("1 > custom_header: container/request\n")));
+
+
+ // --- container response log entry
+ // container added header to the response and it was logged
+ assertThat(getLoggedRecords().get(2).getMessage(),
+ containsString("1 < custom_header: container/response\n"));
+
+ // --- client response log entry
+ // client received header
+ assertThat(getLoggedRecords().get(3).getMessage(),
+ containsString("1 < custom_header: container/response\n"));
+ assertThat(getLoggedRecords().get(3).getMessage(),
+ not(containsString("1 < custom_header: client/response\n")));
+
+ }
+
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyReaderUnsupportedTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyReaderUnsupportedTest.java
new file mode 100644
index 0000000..cdd4965
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyReaderUnsupportedTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test case for unsupported media type.
+ *
+ * @author Miroslav Fuksa
+ */
+public class MessageBodyReaderUnsupportedTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ // TestEntityProvider must not be registered in the application for this test case.
+ return new ResourceConfig(Resource.class);
+ }
+
+ /**
+ * Send request to with application/json content to server where JsonJaxbBinder is not registered. UNSUPPORTED_MEDIA_TYPE
+ * should be returned.
+ */
+ @Test
+ public void testUnsupportedMessageBodyReader() {
+ client().register(new TestEntityProvider());
+ TestEntity entity = new TestEntity("testEntity");
+ Response response = target().path("test").request(TestEntityProvider.TEST_ENTITY_TYPE)
+ .post(Entity.entity(entity, TestEntityProvider.TEST_ENTITY_TYPE));
+
+ // TestEntityProvider is not registered on the server and therefore the server should return UNSUPPORTED_MEDIA_TYPE
+ assertEquals(Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode(), response.getStatus());
+ assertFalse(Resource.methodCalled);
+ String responseEntity = response.readEntity(String.class);
+ assertTrue((responseEntity == null) || (responseEntity.length() == 0));
+ }
+
+ /**
+ * Test Resource class.
+ *
+ * @author Miroslav Fuksa
+ */
+ @Path("test")
+ public static class Resource {
+
+ private static volatile boolean methodCalled;
+
+ /**
+ * Resource method producing a {@code null} result.
+ *
+ * @param entity test entity.
+ * @return {@code null}.
+ */
+ @POST
+ @Produces(TestEntityProvider.TEST_ENTITY)
+ @Consumes(TestEntityProvider.TEST_ENTITY)
+ @SuppressWarnings("UnusedParameters")
+ public TestEntity processEntityAndProduceNull(TestEntity entity) {
+ methodCalled = true;
+ return null;
+ }
+ }
+
+ /**
+ * Test bean.
+ *
+ * @author Miroslav Fuksa
+ */
+ public static class TestEntity {
+
+ private final String value;
+
+ /**
+ * Get value.
+ *
+ * @return value.
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Create new test entity.
+ *
+ * @param value entity value.
+ */
+ public TestEntity(String value) {
+ super();
+ this.value = value;
+ }
+ }
+
+ /**
+ * Custom test entity provider.
+ */
+ @Produces("test/entity")
+ @Consumes("test/entity")
+ public static class TestEntityProvider implements MessageBodyReader<TestEntity>, MessageBodyWriter<TestEntity> {
+ /**
+ * Test bean media type string.
+ */
+ public static final String TEST_ENTITY = "test/entity";
+ /**
+ * Test bean media type.
+ */
+ public static final MediaType TEST_ENTITY_TYPE = MediaType.valueOf(TEST_ENTITY);
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return TestEntity.class == type && TEST_ENTITY_TYPE.equals(mediaType);
+ }
+
+ @Override
+ public TestEntity readFrom(Class<TestEntity> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return new TestEntity(ReaderWriter.readFromAsString(entityStream, mediaType));
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return TestEntity.class == type && TEST_ENTITY_TYPE.equals(mediaType);
+ }
+
+ @Override
+ public long getSize(TestEntity testEntity,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(TestEntity testEntity,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ ReaderWriter.writeToAsString(testEntity.getValue(), entityStream, mediaType);
+ }
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWorkerInheritanceTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWorkerInheritanceTest.java
new file mode 100644
index 0000000..81d2fa9
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWorkerInheritanceTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test-case for JERSEY-1481.
+ *
+ * {@link JacksonFeature Jackson provider} should not take precedence over our
+ * custom provider.
+ *
+ * @author Michal Gajdos
+ */
+public class MessageBodyWorkerInheritanceTest extends JerseyTest {
+
+ public static interface Model<T> {
+
+ public T getValue();
+ }
+
+ public static class StringModel implements Model<String> {
+
+ private final String value;
+
+ public StringModel(final String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static interface InterfaceType extends Model {
+ }
+
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Provider
+ public static class ModelReader<T extends Model> implements MessageBodyReader<T> {
+
+ @Override
+ public boolean isReadable(
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+
+ return Model.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public T readFrom(
+ Class<T> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+
+ return (T) new InterfaceType() {
+ @Override
+ public Object getValue() {
+ return "fromInterfaceTypeReader";
+ }
+ };
+ }
+ }
+
+ @Provider
+ public abstract static class BaseProvider<T> implements MessageBodyWriter<T> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(final T t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final T t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(getContent(t).getBytes("UTF-8"));
+ }
+
+ public abstract String getContent(T proxy);
+ }
+
+ @Provider
+ @Produces(MediaType.APPLICATION_JSON)
+ public static class GenericModelWriter extends BaseProvider<Model> {
+
+ @Override
+ public String getContent(final Model proxy) {
+ return "{\"bar\":\"" + proxy.getValue() + "\"}";
+ }
+ }
+
+ @Provider
+ @Produces(MediaType.APPLICATION_JSON)
+ public static class IntegerModelWriter extends BaseProvider<Model<Integer>> {
+
+ @Override
+ public String getContent(final Model<Integer> proxy) {
+ return "{\"foo\":\"" + proxy.getValue() + "\"}";
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ public Model<String> getStringModel() {
+ return new StringModel("foo");
+ }
+
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String post(InterfaceType t) {
+ return t.getValue().toString();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class)
+ .register(GenericModelWriter.class)
+ .register(ModelReader.class)
+ .register(JacksonFeature.class);
+ }
+
+ @Test
+ public void testMessageBodyWorkerInheritance() throws Exception {
+ assertEquals("{\"bar\":\"foo\"}", target().path("resource").request(MediaType.APPLICATION_JSON_TYPE).get(String.class));
+ }
+
+ @Test
+ public void testMessageBodyWorkerInterfaceInheritance() throws Exception {
+
+ final Response response = target().path("resource")
+ .request().post(Entity.json("{\"value\":\"ignored\"}"));
+
+ assertEquals(200, response.getStatus());
+ assertEquals("fromInterfaceTypeReader", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWriterObjectDistanceTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWriterObjectDistanceTest.java
new file mode 100644
index 0000000..4a792e0
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/MessageBodyWriterObjectDistanceTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Object.class needs special handling when computing type distance - it should be always further than any other
+ * implemented interface.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@SuppressWarnings("WeakerAccess")
+public class MessageBodyWriterObjectDistanceTest extends JerseyTest {
+
+ public interface InterfaceA {
+
+ }
+
+ public interface InterfaceB extends InterfaceA {
+
+ }
+
+ @Provider
+ @Produces("application/test")
+ public static class ObjectWriter implements MessageBodyWriter<Object> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public long getSize(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ entityStream.write("object".getBytes("UTF-8"));
+ }
+ }
+
+ @Provider
+ @Produces("application/test")
+ public static class InterfaceAWriter implements MessageBodyWriter<InterfaceA> {
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return InterfaceA.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(InterfaceA interfaceA, Class<?> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(InterfaceA interfaceA, Class<?> type, Type genericType, Annotation[] annotations,
+ MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ entityStream.write(InterfaceA.class.getSimpleName().getBytes("UTF-8"));
+ }
+ }
+
+ @Path("resource")
+ public static class Resource {
+
+ @GET
+ @Produces("application/test")
+ public InterfaceB getStringModel() {
+ return new InterfaceB() {
+ };
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class)
+ .register(ObjectWriter.class)
+ .register(InterfaceAWriter.class);
+ }
+
+ @Test
+ public void testMessageBodyWriterObjectDistance() throws Exception {
+ assertEquals(InterfaceA.class.getSimpleName(),
+ target().path("resource").request("application/test").get(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NoEntityTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NoEntityTest.java
new file mode 100644
index 0000000..201f846
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NoEntityTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Tests that no content type is sent when an entity is not present.
+ *
+ * @author Miroslav Fuksa
+ */
+public class NoEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(MyResource.class, MoxyJsonFeature.class);
+ return resourceConfig;
+ }
+
+ @XmlRootElement
+ public static class MyEntity {
+
+ @XmlAttribute
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+ @Path("resource")
+ public static class MyResource {
+
+ @GET
+ @Produces("application/json")
+ @Path("no-entity")
+ public Response getNoEntity() {
+ return Response.status(204).build();
+ }
+
+ @GET
+ @Produces("application/json")
+ @Path("entity")
+ public Response getEntity() {
+ MyEntity myEntity = new MyEntity();
+ myEntity.setName("hello");
+ return Response.status(200).entity(myEntity).build();
+ }
+
+ @GET
+ @Produces("text/plain")
+ @Path("string")
+ public Response getEmptyString() {
+
+ return Response.status(204).entity("").build();
+ }
+
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(
+ new LoggingFeature(Logger.getLogger(NoEntityTest.class.toString()), LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ /**
+ * Tests that returned media type is null when no entity is sent.
+ */
+ @Test
+ public void testNoEntity() {
+ Response response = target().path("resource/no-entity").request(MediaType.APPLICATION_JSON_TYPE).get();
+ MyEntity myEntity = response.readEntity(MyEntity.class);
+ assertNull(myEntity);
+ assertEquals(204, response.getStatus());
+ assertNull(response.getMediaType());
+ }
+
+ /**
+ * Tests that correct media type is returned.
+ */
+ @Test
+ public void testEntity() {
+ Response response = target().path("resource/entity").request(MediaType.APPLICATION_JSON_TYPE).get();
+ MyEntity myEntity = response.readEntity(MyEntity.class);
+ assertEquals("hello", myEntity.getName());
+ assertEquals(200, response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
+ }
+
+ /**
+ * Tests that entity is read as null when no entity is sent with 204 response status.
+ * Currently this test throws an exception when trying to read the entity.
+ * <p/>
+ * Exception:
+ * <p/>
+ * org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
+ * MessageBodyReader not found for media type=text/plain,
+ * type=class org.glassfish.jersey.tests.e2e.common.NoEntityTest$MyEntity,
+ * genericType=class org.glassfish.jersey.tests.e2e.common.NoEntityTest$MyEntity.
+ * <p/>
+ * https://java.net/jira/browse/JERSEY-1994
+ */
+ @Test
+ @Ignore("see https://java.net/jira/browse/JERSEY-1994")
+ public void testNoEntityString() {
+ Response response = target().path("resource/string").request().get();
+ MyEntity myEntity = response.readEntity(MyEntity.class);
+ assertNull(myEntity);
+ assertEquals(204, response.getStatus());
+ assertEquals("text/plain", response.getMediaType());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new SimpleTestContainerFactory();
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NonPublicNonStaticTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NonPublicNonStaticTest.java
new file mode 100644
index 0000000..f28905c
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/NonPublicNonStaticTest.java
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests deployment of non-standard or invalid resources and providers.
+ * <p/>
+ * The tests are checking, that the failure (if expected) takes place in the expected time (during deployment,
+ * or on first request).
+ *
+ * @author Paul Sandoz
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({NonPublicNonStaticTest.NonStaticResourceTest.class,
+ NonPublicNonStaticTest.NonStaticResourceSubResourceTest.class,
+ NonPublicNonStaticTest.NonPublicResourceTest.class,
+ NonPublicNonStaticTest.NonPublicResourceSubResourceTest.class,
+ NonPublicNonStaticTest.AbstractResourceTest.class,
+ NonPublicNonStaticTest.AbstractResourceSubResourceTest.class,
+ NonPublicNonStaticTest.InterfaceResourceTest.class,
+ NonPublicNonStaticTest.InterfaceResourceSubResourceTest.class,
+ NonPublicNonStaticTest.NonPublicResourceWithConstructorTest.class,
+ NonPublicNonStaticTest.NonPublicResourceSubresourceWithConstructorTest.class,
+ NonPublicNonStaticTest.PublicResourceWithPrivateConstructorTest.class,
+ NonPublicNonStaticTest.NonStaticProviderTest.class,
+ NonPublicNonStaticTest.NonPublicProviderTest.class,
+ NonPublicNonStaticTest.PublicProviderWithPrivateConstructorTest.class})
+public class NonPublicNonStaticTest {
+
+ // various resources and providers for the test bellow
+ // as we need to create and deploy separate and customized resourceConfigs for each test case,
+ // the testcases are encapsulated in inner-classes, which are subclasses of JerseyTest.
+ // Those resources and providers are, however in the outter class (can be reused inside resource configs)
+
+ @Path("/non-static")
+ public class NonStaticResource {
+
+ public String get() {
+ return "Hi";
+ }
+ }
+
+ @Path("/non-static-sub")
+ public static class NonStaticResourceSubResource {
+
+ @Path("class")
+ public Class<NonStaticResource> getClazz() {
+ return NonStaticResource.class;
+ }
+ }
+
+ @Path("/non-public")
+ static class NonPublicResource {
+
+ @GET
+ public String get() {
+ return "hi";
+ }
+ }
+
+ @Path("/non-public-sub")
+ public static class NonPublicResourceSubResource {
+
+ @Path("class")
+ public Class<NonPublicResource> getClazz() {
+ return NonPublicResource.class;
+ }
+ }
+
+ @Path("/abstract")
+ public abstract static class AbstractResource {
+
+ @GET
+ public String get() {
+ return "Hi!";
+ }
+ }
+
+ @Path("/abstract-sub")
+ public static class AbstractResourceSubResource {
+
+ @Path("class")
+ public Class<AbstractResource> getClazz() {
+ return AbstractResource.class;
+ }
+ }
+
+ @Path("interface")
+ public static interface InterfaceResource {
+ }
+
+ @Path("interface-sub")
+ public static class InterfaceResourceSubResource {
+
+ @Path("class")
+ public Class<InterfaceResource> getClazz() {
+ return InterfaceResource.class;
+ }
+ }
+
+ @Path("non-public-with-constructor")
+ static class NonPublicResourceWithConstructor {
+
+ public NonPublicResourceWithConstructor() {
+ }
+
+ @GET
+ public String get() {
+ return "Hi!";
+ }
+ }
+
+ @Path("non-public-sub-with-constructor")
+ public static class NonPublicResourceSubResourceWithConstructor {
+
+ @Path("class")
+ public Class<NonPublicResourceWithConstructor> getClazz() {
+ return NonPublicResourceWithConstructor.class;
+ }
+ }
+
+ @Path("public-with-private-constructor")
+ public static class PublicResourceWithPrivateConstructor {
+
+ private PublicResourceWithPrivateConstructor() {
+ }
+
+ @GET
+ public String get() {
+ return "Hi!";
+ }
+ }
+
+ @Path("provider-resource")
+ public static class ProviderResource {
+
+ @GET
+ public String get() {
+ return "Hi!";
+ }
+ }
+
+ @Provider
+ public class NonStaticProvider implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(s.getBytes());
+ }
+ }
+
+ @Provider
+ static class NonPublicProvider implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ final String wrapped = ">> " + s + " <<";
+ entityStream.write(wrapped.getBytes());
+ }
+ }
+
+ @Provider
+ static class PublicProviderWithPrivateConstructor implements MessageBodyWriter<String> {
+
+ private PublicProviderWithPrivateConstructor() {
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(s.getBytes());
+ }
+ }
+
+ @Provider
+ public abstract static class AbstractProvider implements MessageBodyWriter<String> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(s.getBytes());
+ }
+ }
+
+ // Inner test classes - each needed resource config variation has its own inner class
+
+ public static class NonStaticResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(NonStaticResource.class);
+ }
+
+ @Test
+ public void testNonStaticResource() throws IOException {
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ boolean firstFound = false;
+ boolean secondFound = false;
+ for (LogRecord record : loggedRecords) {
+ if (record.getMessage().contains("cannot be instantiated and will be ignored")) {
+ firstFound = true;
+ } else if (record.getMessage().contains("is empty. It has no resource")) {
+ secondFound = true;
+ }
+ if (firstFound && secondFound) {
+ break;
+ }
+ }
+ assertTrue("Expected log message (1st) was not found.", firstFound);
+ assertTrue("Expected log message (2nd) was not found.", secondFound);
+ }
+ }
+
+ public static class NonStaticResourceSubResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(NonStaticResourceSubResource.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testNonStaticResource() throws IOException {
+ target().path("/non-static-sub/class").request().get(String.class);
+ }
+ }
+
+ public static class NonPublicResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(NonPublicResource.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testNonPublicResource() throws IOException {
+ target().path("/non-public").request().get(String.class);
+ }
+ }
+
+ public static class NonPublicResourceSubResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(NonPublicResourceSubResource.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testNonPublicResource() throws IOException {
+ target().path("/non-public-sub/class").request().get(String.class);
+ }
+ }
+
+ public static class AbstractResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(AbstractResource.class);
+ }
+
+ @Test
+ public void testAbstractResource() throws IOException {
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ boolean found = false;
+ for (LogRecord record : loggedRecords) {
+ if (record.getMessage().contains("cannot be instantiated and will be ignored")) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Expected log record was not found.", found);
+ }
+ }
+
+ public static class AbstractResourceSubResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(AbstractResourceSubResource.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testAbstractResourceSubResource() throws IOException {
+ target().path("abstract-sub/class").request().get(String.class);
+ }
+ }
+
+ public static class InterfaceResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(InterfaceResource.class);
+ }
+
+ @Test
+ public void testInterfaceResource() throws IOException {
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ boolean firstFound = false;
+ boolean secondFound = false;
+ for (LogRecord record : loggedRecords) {
+ if (record.getMessage().contains("cannot be instantiated and will be ignored")) {
+ firstFound = true;
+ } else if (record.getMessage().contains("is empty. It has no resource")) {
+ secondFound = true;
+ }
+ if (firstFound && secondFound) {
+ break;
+ }
+ }
+ assertTrue("Expected log message (1st) was not found.", firstFound);
+ assertTrue("Expected log message (2nd) was not found.", secondFound);
+ }
+ }
+
+ public static class InterfaceResourceSubResourceTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(InterfaceResourceSubResource.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testInterfaceResourceSubResource() throws IOException {
+ target().path("interface-sub/class").request().get(String.class);
+ }
+ }
+
+ public static class NonPublicResourceWithConstructorTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(NonPublicResourceWithConstructor.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testNonPublicResourceWithConstructor() throws IOException {
+ target().path("non-public-with-constructor").request().get(String.class);
+ }
+ }
+
+ public static class NonPublicResourceSubresourceWithConstructorTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(NonPublicResourceSubResourceWithConstructor.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testNonPublicResourceSubResourceWithConstructor() throws IOException {
+ target().path("non-public-sub-with-constructor/class").request().get(String.class);
+ }
+ }
+
+ public static class PublicResourceWithPrivateConstructorTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(PublicResourceWithPrivateConstructor.class);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void testPublicResourceWithPrivateConstructor() throws IOException {
+ target().path("public-with-private-constructor").request().get(String.class);
+ }
+ }
+
+ public static class NonStaticProviderTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(ProviderResource.class, NonStaticProvider.class);
+ }
+
+ @Test
+ public void testNonStaticProvider() throws IOException {
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ boolean found = false;
+ for (LogRecord record : loggedRecords) {
+ if (record.getMessage().contains("Instantiation of non-static member classes is not supported")) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Expected log record was not found.", found);
+ }
+ }
+
+ public static class NonPublicProviderTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ return new ResourceConfig(ProviderResource.class, NonPublicProvider.class);
+ }
+
+ @Test
+ public void testNonPublicProvider() throws IOException {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ final String s = target().path("provider-resource").request("text/html").get(String.class);
+ assertEquals(">> Hi! <<", s);
+ }
+ }
+
+ // NOTE - the original Jersey 1 test nonPublicProviderWithConstructor does not make sense considering that it works even
+ // w/o constructor
+
+ public static class PublicProviderWithPrivateConstructorTest extends JerseyTest {
+
+ @Override
+ public ResourceConfig configure() {
+ set(TestProperties.RECORD_LOG_LEVEL, Level.WARNING.intValue());
+ return new ResourceConfig(ProviderResource.class, PublicProviderWithPrivateConstructor.class);
+ }
+
+ @Test
+ public void testNonPublicProvider() throws IOException {
+ final List<LogRecord> loggedRecords = getLoggedRecords();
+ boolean found = false;
+ for (LogRecord record : loggedRecords) {
+ if (record.getMessage().contains("Could not find a suitable constructor")) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Expected log record was not found.", found);
+ }
+ }
+
+ // abstract provider - throws MultiException after calling configure(), but before running the @Test method
+ // the same for interface provider test
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersLegacyOrderingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersLegacyOrderingTest.java
new file mode 100644
index 0000000..012dc88
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersLegacyOrderingTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.MessageProperties;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ProvidersLegacyOrderingTest extends JerseyTest {
+
+ @Produces("application/xml")
+ public static class MyMBW5 implements MessageBodyWriter<Object> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public long getSize(Object myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Object myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Produces("application/*")
+ public static class MyMBW6 implements MessageBodyWriter<Object> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public long getSize(Object myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Object myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Path("/")
+ public static class MyResource {
+
+ @Context
+ MessageBodyWorkers messageBodyWorkers;
+
+ @GET
+ public String getMyType() {
+
+ final Map<MediaType, List<MessageBodyWriter>> writers = messageBodyWorkers.getWriters(MediaType.APPLICATION_XML_TYPE);
+ final List<MessageBodyWriter> messageBodyWriters1 = writers.get(MediaType.APPLICATION_XML_TYPE);
+ final List<MessageBodyWriter> messageBodyWriters2 = writers
+ .get(MediaTypes.getTypeWildCart(MediaType.APPLICATION_XML_TYPE));
+
+ // custom provider has priority - it has to be first
+ assertTrue(messageBodyWriters1.get(0) instanceof MyMBW5);
+ assertTrue(messageBodyWriters2.get(0) instanceof MyMBW6);
+
+ return "";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class, MyMBW5.class, MyMBW6.class);
+ resourceConfig.property(MessageProperties.LEGACY_WORKERS_ORDERING, true);
+ return resourceConfig;
+ }
+
+ @Test
+ public void orderingTest() {
+ try {
+ Response response = target().request("application/test1").get(Response.class);
+
+ assertNotNull(response);
+ assertEquals("Request was not handled correctly, most likely fault in MessageBodyWorker selection.",
+ 200, response.getStatus());
+ } catch (Exception e) {
+ fail("Request was not handled correctly, most likely fault in MessageBodyWorker selection.");
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersOrderingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersOrderingTest.java
new file mode 100644
index 0000000..0d5b748
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ProvidersOrderingTest.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ProvidersOrderingTest extends JerseyTest {
+
+ public static class MyType {
+ }
+
+ public static class MyTypeExt extends MyType {
+ }
+
+ public static class MyTypeExtExt extends MyTypeExt {
+ }
+
+ @Produces("application/test1")
+ public static class MyMBW1 implements MessageBodyWriter<MyType> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBW1(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return false;
+ }
+
+ @Override
+ public long getSize(MyType myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(MyType myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Produces("application/*")
+ public static class MyMBW2 implements MessageBodyWriter<MyType> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBW2(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return false;
+ }
+
+ @Override
+ public long getSize(MyType myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(MyType myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Produces("*/*")
+ public static class MyMBW3 implements MessageBodyWriter<MyType> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBW3(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return true;
+ }
+
+ @Override
+ public long getSize(MyType myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(MyType myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write("test".getBytes());
+ }
+ }
+
+ @Produces("application/*")
+ public static class MyMBW4 implements MessageBodyWriter<MyTypeExt> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBW4(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return false;
+ }
+
+ @Override
+ public long getSize(MyTypeExt myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(MyTypeExt myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Produces("application/xml")
+ public static class MyMBW5 implements MessageBodyWriter<Object> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public long getSize(Object myType, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Object myType,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+ }
+
+ @Consumes("application/test")
+ public static class MyMBR1 implements MessageBodyReader<MyType> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBR1(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return false;
+ }
+
+ @Override
+ public MyType readFrom(Class<MyType> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return null;
+ }
+ }
+
+ @Consumes("application/test1")
+ public static class MyMBR2 implements MessageBodyReader<MyTypeExt> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBR2(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return false;
+ }
+
+ @Override
+ public MyTypeExt readFrom(Class<MyTypeExt> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return null;
+ }
+ }
+
+ @Consumes("application/test1")
+ public static class MyMBR3 implements MessageBodyReader<MyTypeExtExt> {
+
+ private final List<Class<?>> callList;
+
+ public MyMBR3(List<Class<?>> callList) {
+ this.callList = callList;
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ callList.add(this.getClass());
+ return true;
+ }
+
+ @Override
+ public MyTypeExtExt readFrom(Class<MyTypeExtExt> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return new MyTypeExtExt();
+ }
+ }
+
+ @Path("/")
+ public static class MyResource {
+
+ @Context
+ MessageBodyWorkers messageBodyWorkers;
+
+ @PUT
+ @Consumes("application/test1")
+ public MyType getMyType(MyTypeExtExt myType) {
+
+ final Map<MediaType, List<MessageBodyWriter>> writers = messageBodyWorkers.getWriters(MediaType.APPLICATION_XML_TYPE);
+ final List<MessageBodyWriter> messageBodyWriters = writers.get(MediaType.APPLICATION_XML_TYPE);
+
+ assertTrue(messageBodyWriters.get(0) instanceof MyMBW5);
+
+ return myType;
+ }
+
+ @Path("bytearray")
+ @POST
+ public byte[] bytearray(byte[] bytes) {
+ return bytes;
+ }
+ }
+
+ private List<Class<?>> callList;
+
+ @Override
+ protected Application configure() {
+ callList = new ArrayList<>();
+
+ final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class, MyMBW5.class);
+ resourceConfig.registerInstances(new MyMBW1(callList), new MyMBW2(callList), new MyMBW3(callList), new MyMBW4(callList),
+ new MyMBR1(callList), new MyMBR2(callList), new MyMBR3(callList), new MyByteArrayProvider());
+ return resourceConfig;
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void orderingTest() {
+ callList.clear();
+ WebTarget target = target();
+
+ try {
+ Response response = target.request("application/test1")
+ .put(Entity.entity("test", "application/test1"), Response.class);
+
+ assertNotNull(response);
+ assertEquals("Request was not handled correctly, most likely fault in MessageBodyWorker selection.",
+ 200, response.getStatus());
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ fail("Request was not handled correctly, most likely fault in MessageBodyWorker selection.");
+ }
+
+ List<Class<?>> classes = Arrays.asList(
+ MyMBR3.class, // MBR - smallest type distance (MBR1 and MBR2 are not called because of that)
+ MyMBW4.class, // MBW - type distance
+ MyMBW1.class, // MBW - most specific media type application/test1
+ MyMBW2.class, // MBW - application/*
+ MyMBW3.class // MBW - */*, first usable writer (returns true to isWriteable call)
+ );
+
+ assertEquals(classes, callList);
+ }
+
+ @Test
+ public void replaceBuiltInProvider() {
+ callList.clear();
+ WebTarget target = target("bytearray");
+
+ try {
+ Response response = target.request().post(Entity.text("replaceBuiltInProvider"), Response.class);
+
+ assertNotNull(response);
+ assertEquals("Request was not handled correctly, most likely fault in MessageBodyWorker selection.",
+ 200, response.getStatus());
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ fail("Request was not handled correctly, most likely fault in MessageBodyWorker selection.");
+ }
+
+ assertTrue(MyByteArrayProvider.counter == 2); // used to read and write entity on server side.
+
+ }
+
+ @Produces({"application/octet-stream", "*/*"})
+ @Consumes({"application/octet-stream", "*/*"})
+ public static final class MyByteArrayProvider extends AbstractMessageReaderWriterProvider<byte[]> {
+
+ public static int counter = 0;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == byte[].class;
+ }
+
+ @Override
+ public byte[] readFrom(
+ Class<byte[]> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writeTo(entityStream, out);
+ counter++;
+ return out.toByteArray();
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return type == byte[].class;
+ }
+
+ @Override
+ public void writeTo(
+ byte[] t,
+ Class<?> type,
+ Type genericType,
+ Annotation annotations[],
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ counter++;
+ entityStream.write(t);
+ }
+
+ @Override
+ public long getSize(byte[] t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return t.length;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/QueryParamEncodingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/QueryParamEncodingTest.java
new file mode 100644
index 0000000..a5991d9
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/QueryParamEncodingTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import javax.ws.rs.Encoded;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Miroslav Fuksa
+ *
+ */
+public class QueryParamEncodingTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Path("resource")
+ public static class TestResource {
+ @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;
+ }
+ }
+
+ @Test
+ public void testEncoded() {
+ final Response response = target().path("resource/encoded").queryParam("query", "%dummy23+a").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("true:%25dummy23%2Ba", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testDecoded() {
+ final Response response = target().path("resource/decoded").queryParam("query", "%dummy23+a").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("true:%dummy23+a", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ReaderProviderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ReaderProviderTest.java
new file mode 100644
index 0000000..02392bcd
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ReaderProviderTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Testing {@link Reader} on client and server.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ReaderProviderTest extends JerseyTest {
+
+ public static final String GET_READER_RESPONSE = "GET_READER_RESPONSE";
+ public static final String GET_POST_RESPONSE = "GET_POST_RESPONSE";
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ReaderResource.class);
+ }
+
+ @Test
+ public void testReader() {
+ Response response = target().path("test/postReaderGetReader").request().post(Entity.entity(GET_POST_RESPONSE,
+ MediaType.TEXT_PLAIN));
+ assertEquals(200, response.getStatus());
+ assertEquals(GET_POST_RESPONSE, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testGetReader() {
+ Response response = target().path("test/getReader").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals(GET_READER_RESPONSE, response.readEntity(String.class));
+ }
+
+ @Test
+ public void testEmptyReader() throws IOException {
+ Response response = target().path("test/getEmpty").request().get();
+ assertEquals(204, response.getStatus());
+ final Reader reader = response.readEntity(Reader.class);
+ assertNotNull(reader);
+ assertEquals(-1, reader.read());
+ }
+
+ @Test
+ public void testReaderOnClientAsResponseEntity() throws IOException {
+ Response response = target().path("test/getReader").request().get();
+ assertEquals(200, response.getStatus());
+ final Reader reader = response.readEntity(Reader.class);
+ assertNotNull(reader);
+ BufferedReader br = new BufferedReader(reader);
+ assertEquals(GET_READER_RESPONSE, br.readLine());
+ }
+
+ @Test
+ public void testReaderOnClientAsRequestEntity() throws IOException {
+ Response response = target().path("test/postReaderGetReader").request()
+ .post(Entity.entity(new StringReader(GET_POST_RESPONSE), MediaType.TEXT_PLAIN));
+ assertEquals(200, response.getStatus());
+ assertEquals(GET_POST_RESPONSE, response.readEntity(String.class));
+ }
+
+ @Path("test")
+ public static class ReaderResource {
+
+ @POST
+ @Path("postReaderGetReader")
+ public Reader postReader(Reader reader) throws IOException {
+ return reader;
+ }
+
+ @GET
+ @Path("getReader")
+ public Reader getReader() throws IOException {
+ return new StringReader(GET_READER_RESPONSE);
+ }
+
+ @GET
+ @Path("getEmpty")
+ public String getemptyResponse() throws IOException {
+ return null;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/RequestScopeTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/RequestScopeTest.java
new file mode 100644
index 0000000..99a03f0
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/RequestScopeTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * E2E Request Scope Tests.
+ *
+ * @author Michal Gajdos
+ */
+@Ignore("Test Supplier Injection -> this test require dispose() method from Factory")
+public class RequestScopeTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RemoveResource.class)
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindFactory(CloseMeFactory.class, RequestScoped.class).to(CloseMe.class).in(RequestScoped.class);
+ }
+ });
+ }
+
+ public interface CloseMe {
+
+ String eval();
+
+ void close();
+ }
+
+ public static class CloseMeFactory implements DisposableSupplier<CloseMe> {
+
+ private static final CountDownLatch CLOSED_LATCH = new CountDownLatch(1);
+
+ @Override
+ public CloseMe get() {
+ return new CloseMe() {
+ @Override
+ public String eval() {
+ return "foo";
+ }
+
+ @Override
+ public void close() {
+ CLOSED_LATCH.countDown();
+ }
+ };
+ }
+
+ @Override
+ public void dispose(final CloseMe instance) {
+ instance.close();
+ }
+ }
+
+ @Path("remove")
+ public static class RemoveResource {
+
+ private CloseMe closeMe;
+
+ @Inject
+ public RemoveResource(final CloseMe closeMe) {
+ this.closeMe = closeMe;
+ }
+
+ @GET
+ public String get() {
+ return closeMe.eval();
+ }
+ }
+
+ /**
+ * Test that Factory.dispose method is called during release of Request Scope.
+ */
+ @Test
+ public void testRemove() throws Exception {
+ final Response response = target().path("remove").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("foo"));
+
+ assertTrue(CloseMeFactory.CLOSED_LATCH.await(3, TimeUnit.SECONDS));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ResponseLinksTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ResponseLinksTest.java
new file mode 100644
index 0000000..941b3aa
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/ResponseLinksTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import java.net.URI;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Libor Kamolis (libor.kramolis at oracle.com)
+ */
+public class ResponseLinksTest extends JerseyTest {
+
+ @Path("/test")
+ public static class MyResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ /**
+ * Reproducer for JERSEY-2168
+ */
+ @Path("1")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response getLink() {
+ URI link = uriInfo.getAbsolutePathBuilder().queryParam("limit", 50).build();
+ return Response.status(Response.Status.OK).link(link, "prev").build();
+ }
+
+ /**
+ * Reproducer for JERSEY-2168
+ */
+ @Path("2")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response getLinks() {
+ Link link1 = Link.fromUri(uriInfo.getAbsolutePathBuilder().queryParam("limit", 50).build())
+ .rel("prev").build();
+ Link link2 = Link.fromUri(
+ uriInfo.getAbsolutePathBuilder().queryParam("limit", 50).queryParam("action", "next").build()).rel("next")
+ .title("next page").build();
+ return Response.status(Response.Status.OK).links(link1, link2).build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
+ resourceConfig.register(LoggingFeature.class);
+ return resourceConfig;
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(LoggingFeature.class);
+ super.configureClient(config);
+ }
+
+ /**
+ * Reproducer for JERSEY-2168
+ */
+ @Test
+ public void testGetLink() {
+ WebTarget target = target("test");
+ Response response = target.path("1").request(MediaType.APPLICATION_JSON).get();
+ Set<Link> links = response.getLinks();
+ Assert.assertEquals(1, links.size());
+ Assert.assertNotNull(response.getLink("prev"));
+ Assert.assertTrue(response.getLink("prev").getUri().toString().endsWith("1?limit=50"));
+ }
+
+ /**
+ * Reproducer for JERSEY-2168
+ */
+ @Test
+ public void testGetLinks() {
+ WebTarget target = target("test");
+ Response response = target.path("2").request(MediaType.APPLICATION_JSON).get();
+ Set<Link> links = response.getLinks();
+ Assert.assertEquals(2, links.size());
+ Assert.assertNotNull(response.getLink("prev"));
+ Assert.assertTrue(response.getLink("prev").getUri().toString().endsWith("2?limit=50"));
+ Assert.assertNotNull(response.getLink("next"));
+ Assert.assertEquals("next page", response.getLink("next").getTitle());
+ Assert.assertTrue(response.getLink("next").getUri().toString().endsWith("2?limit=50&action=next"));
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/UriComponentTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/UriComponentTest.java
new file mode 100644
index 0000000..5d44b60
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/UriComponentTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.common;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.uri.UriComponent;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Libor Kamolis (libor.kramolis at oracle.com)
+ */
+public class UriComponentTest extends JerseyTest {
+
+ private static final String VALUE_PREFIX = "-<#[";
+ private static final String VALUE_SUFFIX = "]#>-";
+
+ @Path("/test")
+ public static class MyResource {
+ @GET
+ @Path("text")
+ public String getTextValue(@QueryParam("text") String text) {
+ return VALUE_PREFIX + text + VALUE_SUFFIX;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
+ resourceConfig.register(LoggingFeature.class);
+ return resourceConfig;
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(LoggingFeature.class);
+ super.configureClient(config);
+ }
+
+ /**
+ * Reproducer for JERSEY-2260
+ */
+ @Test
+ public void testText() {
+ final String QUERY_RESERVED_CHARS = ";/?:@&=+,$";
+ final String OTHER_SPECIAL_CHARS = "\"\t- \n'";
+
+ testTextImpl("query reserved characters", QUERY_RESERVED_CHARS);
+ testTextImpl("other special characters", OTHER_SPECIAL_CHARS);
+
+ testTextImpl("query reserved characters between template brackets", "{abc" + QUERY_RESERVED_CHARS + "XYZ}");
+ testTextImpl("other special characters between template brackets", "{abc" + OTHER_SPECIAL_CHARS + "XYZ}");
+
+ testTextImpl("json - double quote", "{ \"jmeno\" : \"hodnota\" }");
+ testTextImpl("json - single quote", "{ 'jmeno' : 'hodnota' }");
+ }
+
+ private void testTextImpl(String message, final String text) {
+ String encoded = UriComponent.encode(text, UriComponent.Type.QUERY_PARAM_SPACE_ENCODED);
+ WebTarget target = target("test/text");
+ Response response = target.queryParam("text", encoded).request().get();
+ Assert.assertEquals(200, response.getStatus());
+ String actual = response.readEntity(String.class);
+ Assert.assertEquals(message, VALUE_PREFIX + text + VALUE_SUFFIX, actual);
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/package-info.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/package-info.java
new file mode 100644
index 0000000..05d9d55
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Jersey End to End common test classes.
+ */
+package org.glassfish.jersey.tests.e2e.common;
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/AbstractSlashesWithContextPathTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/AbstractSlashesWithContextPathTest.java
new file mode 100644
index 0000000..d5c4168
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/AbstractSlashesWithContextPathTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.net.URI;
+
+import javax.ws.rs.Encoded;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+
+/**
+ * Abstract Jersey test with prepared resources for URL match
+ * testing on different containers.
+ *
+ * @author Petr Bouda
+ */
+public class AbstractSlashesWithContextPathTest extends JerseyTest {
+
+ public static final String CONTAINER_RESPONSE = "Container-Response";
+ public static final String CONTEXT_PATH = "base";
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(SimpleResource.class,
+ PathParamResource.class,
+ EmptyResource.class,
+ EmptyPathParamResource.class);
+
+ resourceConfig.property(ServerProperties.REDUCE_CONTEXT_PATH_SLASHES_ENABLED, true);
+ return resourceConfig;
+ }
+
+ @Path("simple")
+ public static class SimpleResource {
+
+ @GET
+ public String encoded() {
+ return CONTAINER_RESPONSE;
+ }
+
+ }
+
+ @Path("pathparam")
+ public static class PathParamResource {
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/test")
+ public String hello(@PathParam("bar") final String bar, @PathParam("baz") final String baz) {
+ return bar + "-" + baz;
+ }
+ }
+
+ @Path("/")
+ public static class EmptyPathParamResource {
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/test")
+ public String hello(@PathParam("bar") final String bar, @PathParam("baz") final String baz) {
+ return bar + "-" + baz;
+ }
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/testParams")
+ public String helloWithQueryParams(@PathParam("bar") final String bar,
+ @PathParam("baz") final String baz,
+ @QueryParam("bar") final String queryBar,
+ @QueryParam("baz") final String queryBaz) {
+ return "PATH PARAM: " + bar + "-" + baz + ", QUERY PARAM " + queryBar + "-" + queryBaz;
+ }
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/encoded")
+ public String getEncoded(@Encoded @QueryParam("query") String queryParam) {
+ return queryParam.equals("%25dummy23%2Ba") + ":" + queryParam;
+ }
+ }
+
+ @Path("/")
+ public static class EmptyResource {
+
+ @GET
+ @Path("/test")
+ public String hello() {
+ return CONTAINER_RESPONSE;
+ }
+ }
+
+ protected Response call(String path) {
+ URI hostPort = UriBuilder.fromUri("http://localhost").port(getPort()).build();
+ return client().target(hostPort).path(path).request().get();
+ }
+
+ /**
+ * Context path configuration
+ */
+ @Override
+ protected URI getBaseUri() {
+ URI baseUri = super.getBaseUri();
+ return UriBuilder.fromUri(baseUri).path(CONTEXT_PATH).build();
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/EscapedUriTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/EscapedUriTest.java
new file mode 100644
index 0000000..29aa2c9
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/EscapedUriTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EscapedUriTest extends JerseyContainerTest {
+
+ private static final String RESPONSE = "CONTENT";
+
+ @Path("x%20y")
+ public static class EscapedUriResource {
+
+ private final String context;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public EscapedUriResource() {
+ this("");
+ }
+
+ public EscapedUriResource(final String context) {
+ this.context = context;
+ }
+
+ @GET
+ public String get(@Context final UriInfo info) {
+ assertEquals(context + "/x%20y", info.getAbsolutePath().getRawPath());
+ assertEquals("/", info.getBaseUri().getRawPath());
+ assertEquals(context + "/x y", "/" + info.getPath());
+ assertEquals(context + "/x%20y", "/" + info.getPath(false));
+
+ return RESPONSE;
+ }
+ }
+
+ @Path("non/x y")
+ public static class NonEscapedUriResource extends EscapedUriResource {
+
+ public NonEscapedUriResource() {
+ super("/non");
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(EscapedUriResource.class, NonEscapedUriResource.class);
+ }
+
+ @Test
+ public void testEscaped() {
+ assertThat(target("x%20y").request().get(String.class), is(RESPONSE));
+ }
+
+ @Test
+ public void testNonEscaped() {
+ assertThat(target("non/x y").request().get(String.class), is(RESPONSE));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GrizzlySlashesWithContextPathTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GrizzlySlashesWithContextPathTest.java
new file mode 100644
index 0000000..509fdcf
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GrizzlySlashesWithContextPathTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Test Jersey container implementation of URL resolving.
+ * Slashes before a context path can be omitted depending on
+ * the given property.
+ *
+ * @author Petr Bouda
+ */
+public class GrizzlySlashesWithContextPathTest extends AbstractSlashesWithContextPathTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ @Test
+ public void testSimpleSlashes() {
+ Response result = call(CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("/" + CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("//" + CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("///" + CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("////" + CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithPathParam() {
+ Response result = call("//" + CONTEXT_PATH + "/pathparam/Container/Response/test");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithEmptyPathParam() {
+ Response result = call("//" + CONTEXT_PATH + "/pathparam///test");
+ assertEquals("-", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParam() {
+ Response result = call("//" + CONTEXT_PATH + "///test");
+ assertEquals("-", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testEncodedQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path("//" + CONTEXT_PATH + "///encoded")
+ .queryParam("query", "%dummy23+a");
+
+ Response response = target.request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("true:%25dummy23%2Ba", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParamWithQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path("//" + CONTEXT_PATH + "///testParams")
+ .queryParam("bar", "Container")
+ .queryParam("baz", "Response");
+
+ Response result = target.request().get();
+ assertEquals("PATH PARAM: -, QUERY PARAM Container-Response", result.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GzipContentEncodingTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GzipContentEncodingTest.java
new file mode 100644
index 0000000..61c463e
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/GzipContentEncodingTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.filter.EncodingFilter;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class GzipContentEncodingTest extends JerseyContainerTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get() {
+ return "GET";
+ }
+
+ @POST
+ public String post(final String content) {
+ return content;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, EncodingFilter.class, GZipEncoder.class);
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(new ReaderInterceptor() {
+ @Override
+ public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(new GZIPInputStream(context.getInputStream()));
+ return context.proceed();
+ }
+ });
+ }
+
+ @Test
+ public void testGet() {
+ final Response response = target().request()
+ .header(HttpHeaders.ACCEPT_ENCODING, "gzip")
+ .get();
+
+ assertThat(response.readEntity(String.class), is("GET"));
+ }
+
+ @Test
+ public void testPost() {
+ final Response response = target().request()
+ .header(HttpHeaders.ACCEPT_ENCODING, "gzip")
+ .post(Entity.text("POST"));
+
+ assertThat(response.readEntity(String.class), is("POST"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/HeadTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/HeadTest.java
new file mode 100644
index 0000000..a143d0f
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/HeadTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public class HeadTest extends JerseyContainerTest {
+
+ private static final List<TestContainerFactory> FACTORIES = Arrays.asList(
+ new GrizzlyTestContainerFactory(),
+ new InMemoryTestContainerFactory(),
+ new SimpleTestContainerFactory(),
+ new JettyTestContainerFactory());
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<TestContainerFactory[]> parameters() throws Exception {
+ return FACTORIES.stream().map(input -> new TestContainerFactory[]{input}).collect(Collectors.toList());
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @Path("string")
+ @GET
+ public String getString() {
+ return "GET";
+ }
+
+ @Path("byte")
+ @GET
+ public byte[] getByte() {
+ return "GET".getBytes();
+ }
+
+ @Path("ByteArrayInputStream")
+ @GET
+ public InputStream getInputStream() {
+ return new ByteArrayInputStream("GET".getBytes());
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testHeadString() {
+ _testHead("string", MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ @Test
+ public void testHeadByte() {
+ _testHead("byte", MediaType.APPLICATION_OCTET_STREAM_TYPE);
+ }
+
+ @Test
+ public void testHeadByteArrayInputStream() {
+ _testHead("ByteArrayInputStream", MediaType.APPLICATION_OCTET_STREAM_TYPE);
+ }
+
+ private void _testHead(final String path, final MediaType mediaType) {
+ final Response response = target(path).request(mediaType).head();
+ assertThat(response.getStatus(), is(200));
+
+ final String lengthStr = response.getHeaderString(HttpHeaders.CONTENT_LENGTH);
+ assertThat(lengthStr, notNullValue());
+ assertThat(Integer.parseInt(lengthStr), is(3));
+ assertThat(response.getMediaType(), is(mediaType));
+ assertFalse(response.hasEntity());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JdkSlashesWithContextPathTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JdkSlashesWithContextPathTest.java
new file mode 100644
index 0000000..b2276f4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JdkSlashesWithContextPathTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Ignore;
+import org.junit.Test;
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Test Jersey container implementation of URL resolving.
+ * JDK Server does not support multiple slashes before the context-path,
+ * in case of multiple slashes server does not match the processing handler and
+ * therefore Jersey Request cannot be created and processed.
+ *
+ * @author Petr Bouda
+ */
+public class JdkSlashesWithContextPathTest extends AbstractSlashesWithContextPathTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JdkHttpServerTestContainerFactory();
+ }
+
+ @Test
+ public void testSimpleSlashes() {
+ Response result = call(CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("/" + CONTEXT_PATH + "/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithPathParam() {
+ Response result = call(CONTEXT_PATH + "/pathparam/Container/Response/test");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithEmptyPathParam() {
+ Response result = call(CONTEXT_PATH + "/pathparam///test");
+ assertEquals("-", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParam() {
+ Response result = call(CONTEXT_PATH + "///test");
+ assertEquals("-", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParamWithQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path(CONTEXT_PATH + "///testParams")
+ .queryParam("bar", "Container")
+ .queryParam("baz", "Response");
+
+ Response result = target.request().get();
+ assertEquals("PATH PARAM: -, QUERY PARAM Container-Response", result.readEntity(String.class));
+ }
+
+ @Test
+ @Ignore("failing with JDK container.")
+ public void testEncodedQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path("//" + CONTEXT_PATH + "///encoded")
+ .queryParam("query", "%dummy23+a");
+
+ Response response = target.request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("true:%25dummy23%2Ba", response.readEntity(String.class));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java
new file mode 100644
index 0000000..17c8c67
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer tests for JERSEY-2462 on Grizzly, Jetty and Simple HTTP server.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({Jersey2462Test.GrizzlyContainerTest.class,
+ Jersey2462Test.JettyContainerTest.class,
+ Jersey2462Test.SimpleContainerTest.class})
+public class Jersey2462Test {
+ private static final String REQUEST_NUMBER = "request-number";
+
+ /**
+ * Test resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+ @Path("echo")
+ public static class EchoResource {
+
+ /**
+ * Echoes the input message.
+ *
+ * @param message input message.
+ * @return echoed input message.
+ */
+ @POST
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public String echo(String message) {
+ return message + "" + this.getClass().getPackage().getName();
+ }
+ }
+
+ /**
+ * Filter testing Grizzly request/response injection support into singleton providers.
+ */
+ @PreMatching
+ public static class GrizzlyRequestFilter implements ContainerRequestFilter {
+ @Inject
+ private Provider<org.glassfish.grizzly.http.server.Request> grizzlyRequest;
+ @Inject
+ private org.glassfish.grizzly.http.server.Response grizzlyResponse;
+
+ @Override
+ public void filter(ContainerRequestContext ctx) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ // First, make sure there are no null injections.
+ if (grizzlyRequest == null) {
+ sb.append("Grizzly Request is null.\n");
+ }
+ if (grizzlyResponse == null) {
+ sb.append("Grizzly Response is null.\n");
+ }
+
+ if (sb.length() > 0) {
+ ctx.abortWith(Response.serverError().entity(sb.toString()).build());
+ }
+
+ // let's also test some method calls
+ int flags = 0;
+
+ if ("/jersey-2462".equals(grizzlyRequest.get().getContextPath())) {
+ flags += 1;
+ }
+ if (!grizzlyResponse.isCommitted()) {
+ flags += 10;
+ }
+ final String header = grizzlyRequest.get().getHeader(REQUEST_NUMBER);
+
+ ctx.setEntityStream(new ByteArrayInputStream(("filtered-" + flags + "-" + header).getBytes()));
+ }
+ }
+
+ public static class GrizzlyContainerTest extends JerseyTest {
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return DeploymentContext.builder(new ResourceConfig(EchoResource.class, GrizzlyRequestFilter.class))
+ .contextPath("jersey-2462")
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ /**
+ * Reproducer for JERSEY-2462 on Grizzly container.
+ */
+ @Test
+ public void testReqestReponseInjectionIntoSingletonProvider() {
+ Jersey2462Test.testReqestReponseInjectionIntoSingletonProvider(target());
+ }
+ }
+
+ /**
+ * Filter testing Jetty request/response injection support into singleton providers.
+ */
+ @PreMatching
+ public static class JettyRequestFilter implements ContainerRequestFilter {
+ @Inject
+ private Provider<org.eclipse.jetty.server.Request> jettyRequest;
+ @Inject
+ private Provider<org.eclipse.jetty.server.Response> jettyResponse;
+
+ @Override
+ public void filter(ContainerRequestContext ctx) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ // First, make sure there are no null injections.
+ if (jettyRequest == null) {
+ sb.append("Jetty Request is null.\n");
+ }
+ if (jettyResponse == null) {
+ sb.append("Jetty Response is null.\n");
+ }
+
+ if (sb.length() > 0) {
+ ctx.abortWith(Response.serverError().entity(sb.toString()).build());
+ }
+
+ // let's also test some method calls
+ int flags = 0;
+
+ if ("/echo".equals(jettyRequest.get().getPathInfo())) {
+ flags += 1;
+ }
+ if (!jettyResponse.get().isCommitted()) {
+ flags += 10;
+ }
+ final String header = jettyRequest.get().getHeader(REQUEST_NUMBER);
+
+ ctx.setEntityStream(new ByteArrayInputStream(("filtered-" + flags + "-" + header).getBytes()));
+ }
+ }
+
+
+ public static class JettyContainerTest extends JerseyTest {
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return DeploymentContext.builder(new ResourceConfig(EchoResource.class, JettyRequestFilter.class))
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JettyTestContainerFactory();
+ }
+
+ /**
+ * Reproducer for JERSEY-2462 on Grizzly container.
+ */
+ @Test
+ public void testReqestReponseInjectionIntoSingletonProvider() {
+ Jersey2462Test.testReqestReponseInjectionIntoSingletonProvider(target());
+ }
+ }
+
+ /**
+ * Filter testing Simple framework request/response injection support into singleton providers.
+ */
+ @PreMatching
+ public static class SimpleRequestFilter implements ContainerRequestFilter {
+ @Inject
+ private org.simpleframework.http.Request simpleRequest;
+ @Inject
+ private org.simpleframework.http.Response simpleResponse;
+
+ @Override
+ public void filter(ContainerRequestContext ctx) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ // First, make sure there are no null injections.
+ if (simpleRequest == null) {
+ sb.append("Simple HTTP framework Request is null.\n");
+ }
+ if (simpleResponse == null) {
+ sb.append("Simple HTTP framework Response is null.\n");
+ }
+
+ if (sb.length() > 0) {
+ ctx.abortWith(Response.serverError().entity(sb.toString()).build());
+ }
+
+ // let's also test some method calls
+ int flags = 0;
+
+ if ("/echo".equals(simpleRequest.getAddress().getPath().getPath())) {
+ flags += 1;
+ }
+ if (!simpleResponse.isCommitted()) {
+ flags += 10;
+ }
+ final String header = simpleRequest.getValue(REQUEST_NUMBER);
+
+ ctx.setEntityStream(new ByteArrayInputStream(("filtered-" + flags + "-" + header).getBytes()));
+ }
+ }
+
+ public static class SimpleContainerTest extends JerseyTest {
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return DeploymentContext.builder(new ResourceConfig(EchoResource.class, SimpleRequestFilter.class))
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new SimpleTestContainerFactory();
+ }
+
+ /**
+ * Reproducer for JERSEY-2462 on Grizzly container.
+ */
+ @Test
+ public void testReqestReponseInjectionIntoSingletonProvider() {
+ Jersey2462Test.testReqestReponseInjectionIntoSingletonProvider(target());
+ }
+ }
+
+ /**
+ * Reproducer method for JERSEY-2462.
+ */
+ public static void testReqestReponseInjectionIntoSingletonProvider(WebTarget target) {
+ for (int i = 0; i < 10; i++) {
+ String response = target.path("echo").request().header(REQUEST_NUMBER, i)
+ .post(Entity.text("test"), String.class);
+ // Assert that the request has been filtered and processed by the echo method.
+ assertEquals(new EchoResource().echo("filtered-11-" + i), response);
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java
new file mode 100644
index 0000000..fe2b087
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.netty.NettyTestContainerFactory;
+import org.glassfish.jersey.test.simple.SimpleTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(Parameterized.class)
+public abstract class JerseyContainerTest extends JerseyTest {
+
+ private static final List<TestContainerFactory> FACTORIES = Arrays.asList(
+ new GrizzlyTestContainerFactory(),
+ new InMemoryTestContainerFactory(),
+ new SimpleTestContainerFactory(),
+ new JdkHttpServerTestContainerFactory(),
+ new JettyTestContainerFactory(),
+ new NettyTestContainerFactory()
+ );
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<TestContainerFactory[]> parameters() throws Exception {
+ return FACTORIES.stream().map(input -> new TestContainerFactory[]{input}).collect(Collectors.toList());
+ }
+
+
+ @Parameterized.Parameter(0)
+ public TestContainerFactory factory;
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return factory;
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JettyEmptyHeaderParamTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JettyEmptyHeaderParamTest.java
new file mode 100644
index 0000000..4af03c6
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JettyEmptyHeaderParamTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests Jetty getHeader() - returns null in when the header
+ * is not present and even though the header is empty string.
+ *
+ * ISSUE: JERSEY-2917
+ *
+ * @author Petr Bouda
+ * */
+public class JettyEmptyHeaderParamTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HeaderResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new JettyTestContainerFactory();
+ }
+
+ @Path("test")
+ public static class HeaderResource {
+
+ @GET
+ public String get(@HeaderParam("a") String value) {
+ return value;
+ }
+
+ }
+
+ @Test
+ public void testNullHeader() throws Exception {
+ String response = target("test").request().get(String.class);
+ assertEquals("", response);
+ }
+
+ @Test
+ public void testEmptyHeader() throws Exception {
+ String response = target("test").request().header("a", "").get(String.class);
+ assertEquals("", response);
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/LeadingSlashesTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/LeadingSlashesTest.java
new file mode 100644
index 0000000..f9b3bd8
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/LeadingSlashesTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.net.URI;
+
+import javax.ws.rs.Encoded;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertNotEquals;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Test Jersey container implementation of URL resolving.
+ * In this test there is no context path that means that
+ * slashes in URL are part of Resource address and couldn't
+ * be deleted.
+ *
+ * @author Petr Bouda
+ */
+public class LeadingSlashesTest extends JerseyContainerTest {
+
+ public static final String CONTAINER_RESPONSE = "Container-Response";
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig(SimpleResource.class,
+ EmptyResource.class,
+ EmptyPathParamResource.class);
+
+ resourceConfig.property(ServerProperties.REDUCE_CONTEXT_PATH_SLASHES_ENABLED, true);
+ return resourceConfig;
+ }
+
+ @Path("simple")
+ public static class SimpleResource {
+
+ @GET
+ public String encoded() {
+ return CONTAINER_RESPONSE;
+ }
+
+ }
+
+ @Path("/")
+ public static class EmptyPathParamResource {
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/test")
+ public String getHello(@PathParam("bar") final String bar, @PathParam("baz") final String baz) {
+ return bar + "-" + baz;
+ }
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/testParams")
+ public String helloWithQueryParams(@PathParam("bar") final String bar, @PathParam("baz") final String baz,
+ @QueryParam("bar") final String queryBar, @QueryParam("baz") final String queryBaz) {
+ return "PATH PARAM: " + bar + "-" + baz + ", QUERY PARAM " + queryBar + "-" + queryBaz;
+ }
+
+ @GET
+ @Path("{bar:.*}/{baz:.*}/encoded")
+ public String getEncoded(@Encoded @QueryParam("query") String queryParam) {
+ return queryParam.equals("%25dummy23%2Ba") + ":" + queryParam;
+ }
+ }
+
+ @Path("/")
+ public static class EmptyResource {
+
+ @GET
+ @Path("/test")
+ public String getHello() {
+ return CONTAINER_RESPONSE;
+ }
+ }
+
+ @Test
+ public void testSimpleSlashes() {
+ Response result = call("/simple");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+
+ result = call("//simple");
+ assertNotEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmpty() {
+ Response result = call("/test");
+ assertEquals(CONTAINER_RESPONSE, result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParam() {
+ Response result = call("///test");
+ assertEquals("-", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testSlashesWithBeginningEmptyPathParamWithQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path("///testParams")
+ .queryParam("bar", "Container")
+ .queryParam("baz", "Response");
+
+ Response result = target.request().get();
+ assertEquals("PATH PARAM: -, QUERY PARAM Container-Response", result.readEntity(String.class));
+ }
+
+ @Test
+ public void testEncodedQueryParams() {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ WebTarget target = client().target(hostPort).path("///encoded")
+ .queryParam("query", "%dummy23+a");
+
+ Response response = target.request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("true:%25dummy23%2Ba", response.readEntity(String.class));
+ }
+
+
+ private Response call(String path) {
+ URI hostPort = UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ return client().target(hostPort).path(path).request().get();
+ }
+
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/MatrixParamTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/MatrixParamTest.java
new file mode 100644
index 0000000..ed96f47
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/MatrixParamTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MatrixParamTest extends JerseyContainerTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String get(@MatrixParam("x") final String x, @MatrixParam("y") final String y) {
+ return y;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testMatrixParam() {
+ assertThat(target().matrixParam("y", "1").request().get(String.class), is("1"));
+ assertThat(target().matrixParam("x", "1").matrixParam("y", "1%20%2B%202").request().get(String.class), is("1 + 2"));
+ assertThat(target().matrixParam("x", "1").matrixParam("y", "1%20%26%202").request().get(String.class), is("1 & 2"));
+ assertThat(target().matrixParam("x", "1").matrixParam("y", "1%20%7C%7C%202").request().get(String.class), is("1 || 2"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/QueryParamTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/QueryParamTest.java
new file mode 100644
index 0000000..7e95477
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/QueryParamTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class QueryParamTest extends JerseyContainerTest {
+
+ @Path("/")
+ public static class Resource {
+ @GET
+ public String get(@QueryParam("x") final String x, @QueryParam("y") final String y) {
+ return y;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testQueryParam() {
+ assertThat(target().queryParam("y", "1 %2B 2").request().get(String.class), is("1 + 2"));
+ assertThat(target().queryParam("x", "1").queryParam("y", "1 + 2").request().get(String.class), is("1 + 2"));
+ assertThat(target().queryParam("x", "1").queryParam("y", "1 %26 2").request().get(String.class), is("1 & 2"));
+ assertThat(target().queryParam("x", "1").queryParam("y", "1 %7C%7C 2").request().get(String.class), is("1 || 2"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterMetadataTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterMetadataTest.java
new file mode 100644
index 0000000..3035489
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterMetadataTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
+import org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ResponseWriterMetadataTest extends JerseyContainerTest {
+
+ public static class ValueHolder {
+
+ private String value;
+
+ public ValueHolder(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ @Provider
+ @Produces("text/plain")
+ public static class ValueHolderWriter implements MessageBodyWriter<ValueHolder> {
+
+ public boolean isWriteable(final Class<?> c, final Type t, final Annotation[] as, final MediaType mediaType) {
+ return ValueHolder.class == c;
+ }
+
+ public long getSize(final ValueHolder s, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ public void writeTo(final ValueHolder s,
+ final Class<?> c,
+ final Type t,
+ final Annotation[] as,
+ final MediaType mt,
+ final MultivaluedMap<String, Object> headers,
+ final OutputStream out) throws IOException, WebApplicationException {
+
+ headers.add("X-BEFORE-WRITE", "foo");
+ out.write(s.value.getBytes());
+ headers.add("X-AFTER-WRITE", "bar");
+ }
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public ValueHolder get() {
+ return new ValueHolder("one");
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, ValueHolderWriter.class)
+ .property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 1);
+ }
+
+ @Test
+ public void testResponse() {
+ final Response response = target().request().get();
+
+ assertThat(response.readEntity(String.class), is("one"));
+ assertThat(response.getHeaderString("X-BEFORE-WRITE"), is("foo"));
+
+ if (factory instanceof InMemoryTestContainerFactory) {
+ assertThat(response.getHeaderString("X-AFTER-WRITE"), is("bar"));
+ } else {
+ assertThat(response.getHeaderString("X-AFTER-WRITE"), nullValue());
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterOutputStreamTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterOutputStreamTest.java
new file mode 100644
index 0000000..7edcbc4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/ResponseWriterOutputStreamTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This is really weird approach and test.
+ *
+ * @author Michal Gajdos
+ */
+public class ResponseWriterOutputStreamTest extends JerseyContainerTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ @Produces("text/plain")
+ public void get(final ContainerRequest context) throws IOException {
+ assertThat(context.getMethod(), is("GET"));
+
+ final ContainerResponse response = new ContainerResponse(context, Response.ok().build());
+ final OutputStream os = context.getResponseWriter()
+ .writeResponseStatusAndHeaders("RESOURCE".getBytes().length, response);
+ os.write("RESOURCE".getBytes());
+ os.close();
+ }
+
+ @POST
+ @Produces("text/plain")
+ public void post(final ContainerRequest context) throws IOException {
+ assertThat(context.getMethod(), is("POST"));
+
+ final String s = context.readEntity(String.class);
+ assertEquals("RESOURCE", s);
+
+ final ContainerResponse response = new ContainerResponse(context, Response.ok().build());
+ final OutputStream os = context.getResponseWriter()
+ .writeResponseStatusAndHeaders("RESOURCE".getBytes().length, response);
+ os.write("RESOURCE".getBytes());
+ os.close();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testGet() {
+ assertThat(target().request().get(String.class), is("RESOURCE"));
+ }
+
+ @Test
+ public void testPost() {
+ assertThat(target().request().post(Entity.text("RESOURCE"), String.class), is("RESOURCE"));
+ }
+
+ @Test
+ public void testAll() {
+ testGet();
+ testPost();
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/TrailingSlashTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/TrailingSlashTest.java
new file mode 100644
index 0000000..b55cb38
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/TrailingSlashTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.container;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class TrailingSlashTest extends JerseyContainerTest {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ @Path("get")
+ public String get() {
+ return "get";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class);
+ }
+
+ @Test
+ public void testSlash() throws Exception {
+ _test("get/");
+ }
+
+ @Test
+ public void testNoSlash() throws Exception {
+ _test("get");
+ }
+
+ private void _test(final String path) {
+ final Response response = target(path).request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("get"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/AccessTokenResource.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/AccessTokenResource.java
new file mode 100644
index 0000000..be10824
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/AccessTokenResource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.oauth1.signature.OAuth1Parameters;
+import org.glassfish.jersey.oauth1.signature.OAuth1Secrets;
+import org.glassfish.jersey.oauth1.signature.OAuth1Signature;
+import org.glassfish.jersey.oauth1.signature.OAuth1SignatureException;
+import org.glassfish.jersey.server.oauth1.internal.OAuthServerRequest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@Path("/access_token")
+public class AccessTokenResource {
+
+ @Inject
+ private OAuth1Signature oAuth1Signature;
+
+ @POST
+ @Produces("text/plain")
+ public String post(@Context ContainerRequestContext request) {
+
+ OAuthServerRequest osr = new OAuthServerRequest(request);
+
+ OAuth1Secrets secrets = new OAuth1Secrets()
+ .consumerSecret("kd94hf93k423kf44").tokenSecret("hdhd0244k9j7ao03");
+
+ OAuth1Parameters params = new OAuth1Parameters().readRequest(osr);
+
+ // ensure query parameters correctly parsed into OAuth parameters object
+ assertEquals(params.getConsumerKey(), "dpf43f3p2l4k3l03");
+ assertEquals(params.getToken(), "hh5s93j4hdidpola");
+ assertEquals(params.getSignatureMethod(), "PLAINTEXT");
+ assertEquals(params.getSignature(), secrets.getConsumerSecret() + "&" + secrets.getTokenSecret());
+ assertEquals(params.getTimestamp(), "1191242092");
+ assertEquals(params.getNonce(), "dji430splmx33448");
+ assertEquals(params.getVersion(), "1.0");
+
+ try {
+ // verify the plaintext signature
+ assertTrue(oAuth1Signature.verify(osr, params, secrets));
+ } catch (OAuth1SignatureException ose) {
+ fail(ose.getMessage());
+ }
+
+ return "oauth_token=nnch734d00sl2jdk&oauth_token_secret=pfkkdhi9sl3r4s00";
+ }
+
+}
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuth2Test.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuth2Test.java
new file mode 100644
index 0000000..77323c4
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuth2Test.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.oauth2.ClientIdentifier;
+import org.glassfish.jersey.client.oauth2.OAuth2ClientSupport;
+import org.glassfish.jersey.client.oauth2.OAuth2CodeGrantFlow;
+import org.glassfish.jersey.client.oauth2.OAuth2Parameters;
+import org.glassfish.jersey.client.oauth2.TokenResult;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests OAuth 2 client.
+ *
+ * @author Miroslav Fuksa
+ */
+public class OAuth2Test extends JerseyTest {
+
+ private static final String STATE = "4564dsf54654fsda654af";
+ private static final String CODE = "code-xyz";
+ private static final String CLIENT_PUBLIC = "clientPublic";
+ private static final String CLIENT_SECRET = "clientSecret";
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(MoxyJsonFeature.class, AuthorizationResource.class)
+ .register(new LoggingFeature(Logger.getAnonymousLogger(), LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ @Path("oauth")
+ public static class AuthorizationResource {
+
+ @POST
+ @Path("access-token")
+ @Produces(MediaType.APPLICATION_JSON)
+ public MyTokenResult getAccessToken(@FormParam("grant_type") String grantType,
+ @FormParam("code") String code,
+ @FormParam("redirect_uri") String redirectUri,
+ @FormParam("client_id") String clientId) {
+ try {
+ assertEquals("authorization_code", grantType);
+ assertEquals("urn:ietf:wg:oauth:2.0:oob", redirectUri);
+ assertEquals(CODE, code);
+ assertEquals(CLIENT_PUBLIC, clientId);
+ } catch (AssertionError e) {
+ e.printStackTrace();
+ throw new BadRequestException(Response.status(400).entity(e.getMessage()).build());
+ }
+
+ final MyTokenResult myTokenResult = new MyTokenResult();
+ myTokenResult.setAccessToken("access-token-aab999f");
+ myTokenResult.setExpiresIn("3600");
+ myTokenResult.setTokenType("access-token");
+ myTokenResult.setRefreshToken("refresh-xyz");
+ return myTokenResult;
+ }
+
+ @GET
+ @Path("authorization")
+ public String authorization(@QueryParam("state") String state,
+ @QueryParam("response_type") String responseType,
+ @QueryParam("scope") String scope,
+ @QueryParam("readOnly") String readOnly,
+ @QueryParam("redirect_uri") String redirectUri) {
+ try {
+ assertEquals("code", responseType);
+ assertEquals(STATE, state);
+ assertEquals("urn:ietf:wg:oauth:2.0:oob", redirectUri);
+ assertEquals("contact", scope);
+ assertEquals("true", readOnly);
+ } catch (AssertionError e) {
+ e.printStackTrace();
+ throw new BadRequestException(Response.status(400).entity(e.getMessage()).build());
+ }
+ return CODE;
+ }
+
+ @POST
+ @Path("refresh-token")
+ @Produces(MediaType.APPLICATION_JSON)
+ public String refreshToken(@FormParam("grant_type") String grantType,
+ @FormParam("refresh_token") String refreshToken,
+ @HeaderParam("isArray") @DefaultValue("false") boolean isArray) {
+ try {
+ assertEquals("refresh_token", grantType);
+ assertEquals("refresh-xyz", refreshToken);
+ } catch (AssertionError e) {
+ e.printStackTrace();
+ throw new BadRequestException(Response.status(400).entity(e.getMessage()).build());
+ }
+
+ return isArray
+ ? "{\"access_token\":[\"access-token-new\"],\"expires_in\":\"3600\",\"token_type\":\"access-token\"}"
+ : "{\"access_token\":\"access-token-new\",\"expires_in\":\"3600\",\"token_type\":\"access-token\"}";
+ }
+ }
+
+ @Test
+ public void testFlow() {
+ testFlow(false);
+ }
+
+ @Test
+ public void testFlowWithArrayInResponse() {
+ testFlow(true);
+ }
+
+ private void testFlow(final boolean isArray) {
+ ClientIdentifier clientId = new ClientIdentifier(CLIENT_PUBLIC, CLIENT_SECRET);
+ final String authUri = UriBuilder.fromUri(getBaseUri()).path("oauth").path("authorization").build().toString();
+ final String accessTokenUri = UriBuilder.fromUri(getBaseUri()).path("oauth").path("access-token").build().toString();
+ final String refreshTokenUri = UriBuilder.fromUri(getBaseUri()).path("oauth").path("refresh-token").build().toString();
+ final String state = STATE;
+
+ final Client client = ClientBuilder.newClient();
+ if (isArray) {
+ client.register(new ClientRequestFilter() {
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().putSingle("isArray", true);
+ }
+ });
+ }
+
+ final OAuth2CodeGrantFlow.Builder builder =
+ OAuth2ClientSupport.authorizationCodeGrantFlowBuilder(clientId, authUri, accessTokenUri);
+ final OAuth2CodeGrantFlow flow = builder
+ .client(client)
+ .refreshTokenUri(refreshTokenUri)
+ .property(OAuth2CodeGrantFlow.Phase.AUTHORIZATION, "readOnly", "true")
+ .property(OAuth2CodeGrantFlow.Phase.AUTHORIZATION, OAuth2Parameters.STATE, state)
+ .scope("contact")
+ .build();
+ final String finalAuthorizationUri = flow.start();
+
+ final Response response = ClientBuilder.newClient().target(finalAuthorizationUri).request().get();
+ assertEquals(200, response.getStatus());
+
+ final String code = response.readEntity(String.class);
+ assertEquals(CODE, code);
+
+ final TokenResult result = flow.finish(code, state);
+ assertEquals("access-token-aab999f", result.getAccessToken());
+ assertEquals(new Long(3600), result.getExpiresIn());
+ assertEquals("access-token", result.getTokenType());
+
+ final TokenResult refreshResult = flow.refreshAccessToken(result.getRefreshToken());
+ assertEquals("access-token-new", refreshResult.getAccessToken());
+ assertEquals(new Long(3600), refreshResult.getExpiresIn());
+ assertEquals("access-token", refreshResult.getTokenType());
+
+ if (isArray) {
+ final Collection<String> array = (Collection<String>) refreshResult.getAllProperties().get("access_token");
+
+ assertThat(array.size(), is(1));
+ assertThat(array, hasItem("access-token-new"));
+ }
+ }
+
+ @XmlRootElement
+ public static class MyTokenResult {
+
+ @XmlAttribute(name = "access_token")
+ private String accessToken;
+ @XmlAttribute(name = "expires_in")
+ private String expiresIn;
+ @XmlAttribute(name = "token_type")
+ private String tokenType;
+
+ public String getRefreshToken() {
+ return refreshToken;
+ }
+
+ public void setRefreshToken(String refreshToken) {
+ this.refreshToken = refreshToken;
+ }
+
+ @XmlAttribute(name = "refresh_token")
+ private String refreshToken;
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ public String getExpiresIn() {
+ return expiresIn;
+ }
+
+ public void setExpiresIn(String expiresIn) {
+ this.expiresIn = expiresIn;
+ }
+
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ public void setTokenType(String tokenType) {
+ this.tokenType = tokenType;
+ }
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuthClientServerTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuthClientServerTest.java
new file mode 100644
index 0000000..533e724
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OAuthClientServerTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriBuilder;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.client.oauth1.AccessToken;
+import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
+import org.glassfish.jersey.client.oauth1.OAuth1AuthorizationFlow;
+import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.oauth1.DefaultOAuth1Provider;
+import org.glassfish.jersey.server.oauth1.OAuth1Provider;
+import org.glassfish.jersey.server.oauth1.OAuth1ServerFeature;
+import org.glassfish.jersey.server.oauth1.OAuth1ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+import com.sun.security.auth.UserPrincipal;
+
+/**
+ * Tests client and server OAuth 1 functionality.
+ *
+ * @author Miroslav Fuksa
+ */
+public class OAuthClientServerTest extends JerseyTest {
+
+ private static final String SECRET_CONSUMER_KEY = "secret-consumer-key";
+ private static final String CONSUMER_KEY = "my-consumer-key";
+ private static final String CONSUMER_NAME = "my-consumer";
+ private static final String PROMETHEUS_TOKEN = "prometheus-token";
+ private static final String PROMETHEUS_SECRET = "prometheus-secret";
+
+ @Override
+ protected Application configure() {
+
+ final DefaultOAuth1Provider oAuthProvider = new DefaultOAuth1Provider();
+ oAuthProvider.registerConsumer(CONSUMER_NAME, CONSUMER_KEY,
+ SECRET_CONSUMER_KEY, new MultivaluedHashMap<String, String>());
+
+ final Principal prometheusPrincipal = new Principal() {
+ @Override
+ public String getName() {
+ return "prometheus";
+ }
+ };
+
+ oAuthProvider.addAccessToken(PROMETHEUS_TOKEN, PROMETHEUS_SECRET, CONSUMER_KEY,
+ "http://callback.url", prometheusPrincipal,
+ Arrays.asList("admin", "user").stream().collect(Collectors.toSet()),
+ new MultivaluedHashMap<String, String>());
+ final OAuth1ServerFeature oAuth1ServerFeature = new OAuth1ServerFeature(oAuthProvider,
+ "requestTokenSpecialUri", "accessTokenSpecialUri");
+ final ResourceConfig resourceConfig = new ResourceConfig();
+ resourceConfig.register(oAuth1ServerFeature);
+ resourceConfig.register(MyProtectedResource.class);
+ resourceConfig.register(new LoggingFeature(Logger.getLogger(OAuthClientServerTest.class.getName()),
+ LoggingFeature.Verbosity.PAYLOAD_ANY));
+ resourceConfig.register(OAuthAuthorizationResource.class);
+ resourceConfig.property(OAuth1ServerProperties.TIMESTAMP_UNIT, "SECONDS");
+ resourceConfig.property(OAuth1ServerProperties.MAX_NONCE_CACHE_SIZE, 20);
+ return resourceConfig;
+ }
+
+ @Path("resource")
+ public static class MyProtectedResource {
+
+ @Context
+ private SecurityContext securityContext;
+
+ @GET
+ public String get() {
+ return securityContext.getUserPrincipal().getName();
+ }
+
+ @Path("admin")
+ @GET
+ public boolean getFoo() {
+ return securityContext.isUserInRole("admin");
+ }
+ }
+
+ @Path("user-authorization")
+ public static class OAuthAuthorizationResource {
+
+ @Inject
+ private OAuth1Provider provider;
+
+ @GET
+ public String mustBeGetMethod(@QueryParam("oauth_token") String token) {
+ System.out.println("Token received from user: " + token);
+ final DefaultOAuth1Provider defProvider = (DefaultOAuth1Provider) provider;
+ assertEquals("http://consumer/callback/homer", defProvider.getRequestToken(token).getCallbackUrl());
+
+ return defProvider.authorizeToken(
+ defProvider.getRequestToken(token),
+ new UserPrincipal("homer"),
+ Collections.singleton("user"));
+ }
+ }
+
+ /**
+ * Tests client and server OAuth.
+ * <p/>
+ * Tests authorization flow including the request to a protected resource. The test uses {@link OAuth1AuthorizationFlow}
+ * to perform user authorization and uses authorized client for requesting protected resource.
+ * <p/>
+ * The resource {@link OAuthAuthorizationResource} is used to perform user authorization (this is done
+ * programmatically from the test). Finally, the Access Token is retrieved and used to request the
+ * protected resource. In this resource the user principal is used to return the name of the user stored
+ * in {@link SecurityContext}.
+ */
+ @Test
+ public void testAuthorizationFlow() {
+ String tempCredUri = UriBuilder.fromUri(getBaseUri()).path("requestTokenSpecialUri").build().toString();
+ String accessTokenUri = UriBuilder.fromUri(getBaseUri()).path("accessTokenSpecialUri").build().toString();
+ final String userAuthorizationUri = UriBuilder.fromUri(getBaseUri()).path("user-authorization").build().toString();
+ final OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport
+ .builder(new ConsumerCredentials(CONSUMER_KEY, SECRET_CONSUMER_KEY))
+ .authorizationFlow(tempCredUri, accessTokenUri, userAuthorizationUri)
+ .callbackUri("http://consumer/callback/homer").build();
+
+ final String authUri = authFlow.start();
+ // authorize by a request to authorization URI
+ final Response userAuthResponse = ClientBuilder.newClient().target(authUri).request().get();
+ assertEquals(200, userAuthResponse.getStatus());
+ final String verifier = userAuthResponse.readEntity(String.class);
+ System.out.println("Verifier: " + verifier);
+
+ authFlow.finish(verifier);
+ final Client authorizedClient = authFlow.getAuthorizedClient();
+
+ Response response = authorizedClient.target(getBaseUri()).path("resource")
+ .request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("homer", response.readEntity(String.class));
+
+ response = authorizedClient.target(getBaseUri()).path("resource").path("admin").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals(false, response.readEntity(boolean.class));
+ }
+
+ /**
+ * Tests {@link org.glassfish.jersey.client.oauth1.OAuth1ClientFilter} already configured with Access Token for signature
+ * purposes only.
+ */
+ @Test
+ public void testRequestSigning() {
+ final Feature filterFeature = OAuth1ClientSupport.builder(
+ new ConsumerCredentials(CONSUMER_KEY, SECRET_CONSUMER_KEY)).feature()
+ .accessToken(new AccessToken(PROMETHEUS_TOKEN, PROMETHEUS_SECRET)).build();
+ final Client client = ClientBuilder.newBuilder()
+ .register(filterFeature).build();
+ final URI resourceUri = UriBuilder.fromUri(getBaseUri()).path("resource").build();
+ final WebTarget target = client.target(resourceUri);
+ Response response;
+ for (int i = 0; i < 15; i++) {
+ System.out.println("request: " + i);
+ response = target.request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("prometheus", response.readEntity(String.class));
+ i++;
+ response = target.path("admin").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals(true, response.readEntity(boolean.class));
+ }
+ }
+
+ /**
+ * Tests configuration of the nonce cache on the server side.
+ */
+ @Test
+ public void testRequestSigningWithExceedingCache() {
+ final Feature filterFeature = OAuth1ClientSupport.builder(
+ new ConsumerCredentials(CONSUMER_KEY, SECRET_CONSUMER_KEY)).feature()
+ .accessToken(new AccessToken(PROMETHEUS_TOKEN, PROMETHEUS_SECRET)).build();
+ final Client client = ClientBuilder.newBuilder()
+ .register(filterFeature).build();
+ final URI resourceUri = UriBuilder.fromUri(getBaseUri()).path("resource").build();
+ final WebTarget target = client.target(resourceUri);
+ Response response;
+ for (int i = 0; i < 20; i++) {
+ System.out.println("request: " + i);
+ response = target.request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("prometheus", response.readEntity(String.class));
+ i++;
+ response = target.path("admin").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals(true, response.readEntity(boolean.class));
+ }
+ // now the nonce cache is full
+ response = target.request().get();
+ assertEquals(401, response.getStatus());
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OauthClientAuthorizationFlowTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OauthClientAuthorizationFlowTest.java
new file mode 100644
index 0000000..147772e
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/OauthClientAuthorizationFlowTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import java.lang.reflect.Field;
+import java.net.URI;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.client.oauth1.AccessToken;
+import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
+import org.glassfish.jersey.client.oauth1.OAuth1AuthorizationFlow;
+import org.glassfish.jersey.client.oauth1.OAuth1Builder;
+import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.oauth1.signature.OAuth1Parameters;
+import org.glassfish.jersey.oauth1.signature.OAuth1SignatureFeature;
+import org.glassfish.jersey.oauth1.signature.PlaintextMethod;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+public class OauthClientAuthorizationFlowTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(AccessTokenResource.class, PhotosResource.class, RequestTokenResource.class,
+ OAuth1SignatureFeature.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyTestContainerFactory();
+ }
+
+ /**
+ * Tests mainly the client functionality. The test client registers
+ * {@link org.glassfish.jersey.client.oauth1.OAuth1ClientFilter} and uses the filter only to sign requests. So, it does not
+ * use the filter to perform authorization flow. However, each request that this test performs is actually a request used
+ * during the authorization flow.
+ * <p/>
+ * The server side of this test extracts header authorization values and tests that signatures are
+ * correct for each request type.
+ */
+ @Test
+ public void testOAuthClientFeature() {
+ final URI baseUri = getBaseUri();
+
+ // baseline for requests
+ final OAuth1Builder oAuth1Builder = OAuth1ClientSupport.builder(new ConsumerCredentials("dpf43f3p2l4k3l03",
+ "kd94hf93k423kf44")).timestamp("1191242090").nonce("hsu94j3884jdopsl").signatureMethod(PlaintextMethod.NAME)
+ .version("1.0");
+ final Feature feature = oAuth1Builder.feature().build();
+
+ final Client client = client();
+ client.register(LoggingFeature.class);
+ final WebTarget target = client.target(baseUri);
+
+ // simulate request for Request Token (temporary credentials)
+ String responseEntity = target.path("request_token").register(feature).request().post(Entity.entity("entity",
+ MediaType.TEXT_PLAIN_TYPE), String.class);
+ assertEquals(responseEntity, "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03");
+
+ final Feature feature2 = oAuth1Builder.timestamp("1191242092").nonce("dji430splmx33448").feature().accessToken(new
+ AccessToken("hh5s93j4hdidpola", "hdhd0244k9j7ao03")).build();
+
+ // simulate request for Access Token
+ responseEntity = target.path("access_token").register(feature2).request().post(Entity.entity("entity",
+ MediaType.TEXT_PLAIN_TYPE), String.class);
+ assertEquals(responseEntity, "oauth_token=nnch734d00sl2jdk&oauth_token_secret=pfkkdhi9sl3r4s00");
+
+ final Feature feature3 = oAuth1Builder.nonce("kllo9940pd9333jh").signatureMethod("HMAC-SHA1").timestamp("1191242096")
+ .feature().accessToken(new AccessToken("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")).build();
+
+ // based on Access Token
+ responseEntity = target.path("/photos").register(feature3).queryParam("file", "vacation.jpg").queryParam("size",
+ "original").request().get(String.class);
+
+ assertEquals(responseEntity, "PHOTO");
+ }
+
+ @Test
+ public void testOAuthClientFlow() throws Exception {
+ final String uri = getBaseUri().toString();
+
+ final OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport
+ .builder(new ConsumerCredentials("dpf43f3p2l4k3l03", "kd94hf93k423kf44"))
+ .timestamp("1191242090")
+ .nonce("hsu94j3884jdopsl")
+ .signatureMethod("PLAINTEXT")
+ .authorizationFlow(
+ uri + "request_token",
+ uri + "access_token",
+ uri + "authorize")
+ .enableLogging()
+ .build();
+
+ // Check we have correct authorization URI.
+ final String authorizationUri = authFlow.start();
+ assertThat(authorizationUri, containsString("authorize?oauth_token=hh5s93j4hdidpola"));
+
+ // For the purpose of the test I need parameters (and there is no way how to do it now).
+ final Field paramField = authFlow.getClass().getDeclaredField("parameters");
+ paramField.setAccessible(true);
+ final OAuth1Parameters params = (OAuth1Parameters) paramField.get(authFlow);
+
+ // Update parameters.
+ params.timestamp("1191242092").nonce("dji430splmx33448");
+
+ final AccessToken accessToken = authFlow.finish();
+ assertThat(accessToken, equalTo(new AccessToken("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")));
+
+ // Update parameters before creating a feature (i.e. changing signature method).
+ params.nonce("kllo9940pd9333jh").signatureMethod("HMAC-SHA1").timestamp("1191242096");
+
+ // Check Authorized Client.
+ final Client flowClient = authFlow.getAuthorizedClient().register(LoggingFeature.class);
+
+ String responseEntity = flowClient.target(uri).path("/photos")
+ .queryParam("file", "vacation.jpg")
+ .queryParam("size", "original")
+ .request()
+ .get(String.class);
+
+ assertThat("Flow Authorized Client", responseEntity, equalTo("PHOTO"));
+
+ // Check Feature.
+ final Client featureClient = ClientBuilder.newClient()
+ .register(authFlow.getOAuth1Feature()).register(LoggingFeature.class);
+
+ responseEntity = featureClient.target(uri).path("/photos")
+ .queryParam("file", "vacation.jpg")
+ .queryParam("size", "original")
+ .request()
+ .get(String.class);
+
+ assertThat("Feature Client", responseEntity, equalTo("PHOTO"));
+ }
+}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/PhotosResource.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/PhotosResource.java
new file mode 100644
index 0000000..e9cc2ce
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/PhotosResource.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.oauth1.signature.OAuth1Parameters;
+import org.glassfish.jersey.oauth1.signature.OAuth1Secrets;
+import org.glassfish.jersey.oauth1.signature.OAuth1Signature;
+import org.glassfish.jersey.oauth1.signature.OAuth1SignatureException;
+import org.glassfish.jersey.server.oauth1.internal.OAuthServerRequest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@Path("/photos")
+public class PhotosResource {
+
+ @Inject
+ private OAuth1Signature oAuth1Signature;
+
+ @GET
+ @Produces("text/plain")
+ public String handle(
+ @QueryParam("file") String file,
+ @QueryParam("size") String size,
+ @Context ContainerRequestContext request) {
+
+ OAuthServerRequest osr = new OAuthServerRequest(request);
+
+ OAuth1Secrets secrets = new OAuth1Secrets()
+ .consumerSecret("kd94hf93k423kf44").tokenSecret("pfkkdhi9sl3r4s00");
+
+ OAuth1Parameters params = new OAuth1Parameters().readRequest(osr);
+
+ // ensure query parameters are as expected
+ assertEquals(file, "vacation.jpg");
+ assertEquals(size, "original");
+
+ // ensure query parameters correctly parsed into OAuth parameters object
+ assertEquals(params.getConsumerKey(), "dpf43f3p2l4k3l03");
+ assertEquals(params.getToken(), "nnch734d00sl2jdk");
+ assertEquals(params.getSignatureMethod(), "HMAC-SHA1");
+ assertEquals(params.getTimestamp(), "1191242096");
+ assertEquals(params.getNonce(), "kllo9940pd9333jh");
+ assertEquals(params.getVersion(), "1.0");
+
+ try {
+ // verify the HMAC-SHA1 signature
+ assertTrue(oAuth1Signature.verify(osr, params, secrets));
+ } catch (OAuth1SignatureException ose) {
+ fail(ose.getMessage());
+ }
+
+ return "PHOTO";
+ }
+}
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/RequestTokenResource.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/RequestTokenResource.java
new file mode 100644
index 0000000..7455e62
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/oauth/RequestTokenResource.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.oauth;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.oauth1.signature.OAuth1Parameters;
+import org.glassfish.jersey.oauth1.signature.OAuth1Secrets;
+import org.glassfish.jersey.oauth1.signature.OAuth1Signature;
+import org.glassfish.jersey.oauth1.signature.OAuth1SignatureException;
+import org.glassfish.jersey.server.oauth1.internal.OAuthServerRequest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@Path("/request_token")
+public class RequestTokenResource {
+
+ @Inject
+ private OAuth1Signature oAuth1Signature;
+
+ @POST
+ @Produces("text/plain")
+ public String get(@Context ContainerRequestContext request) {
+
+ OAuthServerRequest osr = new OAuthServerRequest(request);
+
+ OAuth1Secrets secrets = new OAuth1Secrets().consumerSecret("kd94hf93k423kf44");
+
+ OAuth1Parameters params = new OAuth1Parameters().readRequest(osr);
+
+ // ensure parameters correctly parsed into OAuth parameters object
+ assertEquals(params.getConsumerKey(), "dpf43f3p2l4k3l03");
+ assertEquals(params.getSignatureMethod(), "PLAINTEXT");
+ assertEquals(params.getSignature(), secrets.getConsumerSecret() + "&");
+ assertEquals(params.getTimestamp(), "1191242090");
+ assertEquals(params.getNonce(), "hsu94j3884jdopsl");
+ assertEquals(params.getVersion(), "1.0");
+
+ try {
+ // verify the plaintext signature
+ assertTrue(oAuth1Signature.verify(osr, params, secrets));
+ } catch (OAuth1SignatureException ose) {
+ fail(ose.getMessage());
+ }
+
+ return "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03";
+ }
+
+}
+
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/sonar/SonarJerseyE2ETest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/sonar/SonarJerseyE2ETest.java
new file mode 100644
index 0000000..a31248b
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/sonar/SonarJerseyE2ETest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.sonar;
+
+import org.glassfish.jersey.internal.sonar.SonarJerseyCommon;
+import org.glassfish.jersey.server.internal.sonar.SonarJerseyServer;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class SonarJerseyE2ETest {
+
+ @Test
+ public void testJerseyCommonE2E() {
+ Assert.assertEquals("common e2e", new SonarJerseyCommon().e2e());
+ }
+
+ @Test
+ public void testJerseyCoreE2E() {
+ Assert.assertEquals("server e2e", new SonarJerseyServer().e2e());
+ }
+}
diff --git a/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable b/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
new file mode 100644
index 0000000..0d5c7a0
--- /dev/null
+++ b/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
@@ -0,0 +1,3 @@
+org.glassfish.jersey.tests.e2e.common.AutoDiscoverableTest$CommonAutoDiscoverable
+org.glassfish.jersey.tests.e2e.common.AutoDiscoverableTest$ClientAutoDiscoverable
+org.glassfish.jersey.tests.e2e.common.AutoDiscoverableTest$ServerAutoDiscoverable
\ No newline at end of file
diff --git a/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable b/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
new file mode 100644
index 0000000..c95bd54
--- /dev/null
+++ b/tests/e2e/src/test/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
@@ -0,0 +1,3 @@
+org.glassfish.jersey.tests.e2e.common.ForcedAutoDiscoverableTest$CommonAutoDiscoverable
+org.glassfish.jersey.tests.e2e.common.ForcedAutoDiscoverableTest$ClientAutoDiscoverable
+org.glassfish.jersey.tests.e2e.common.ForcedAutoDiscoverableTest$ServerAutoDiscoverable
diff --git a/tests/e2e/src/test/resources/log4j.properties b/tests/e2e/src/test/resources/log4j.properties
new file mode 100644
index 0000000..7c74efa
--- /dev/null
+++ b/tests/e2e/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+log4j.rootCategory=ALL, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout.ConversionPattern=[%30.30c{1}] - %m%n
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
diff --git a/tests/integration/JERSEY-2988/pom.xml b/tests/integration/JERSEY-2988/pom.xml
new file mode 100644
index 0000000..82dc34a
--- /dev/null
+++ b/tests/integration/JERSEY-2988/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.23-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2988</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2988</name>
+
+ <description>
+ Reproducer of JERSEY-2988.
+
+ Jersey does not set locator properly for SingleHk2LocatorManager.
+ </description>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </properties>
+
+ <dependencies>
+ <!-- Jersey -->
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- Weld -->
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>2.0-EDR1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.servlet</groupId>
+ <artifactId>weld-servlet-core</artifactId>
+ <version>3.0.0.Alpha13</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/ContextAwareBean.java b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/ContextAwareBean.java
new file mode 100644
index 0000000..11f7e6a
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/ContextAwareBean.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ContextAwareBean {
+
+ @Context
+ private Configuration field;
+
+ private Configuration setter;
+
+ public Response fieldConfig() {
+ return field == null
+ ? Response.serverError().build()
+ : Response.ok().build();
+ }
+
+ public Response setterConfig() {
+ return setter == null
+ ? Response.serverError().build()
+ : Response.ok().build();
+ }
+
+ @Context
+ public void setConfig(Configuration setter) {
+ this.setter = setter;
+ }
+
+}
diff --git a/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/FieldContextExceptionMapper.java b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/FieldContextExceptionMapper.java
new file mode 100644
index 0000000..38ddd30
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/FieldContextExceptionMapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class FieldContextExceptionMapper implements ExceptionMapper<IllegalStateException> {
+
+ @Context
+ private HttpHeaders field;
+
+ @Override
+ public Response toResponse(IllegalStateException ex) {
+ return Response.status(520)
+ .header("x-test-header", field.getHeaderString("x-test-header"))
+ .build();
+ }
+}
diff --git a/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/SetterContextExceptionMapper.java b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/SetterContextExceptionMapper.java
new file mode 100644
index 0000000..c153e9f
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/SetterContextExceptionMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class SetterContextExceptionMapper implements ExceptionMapper<NullPointerException> {
+
+ private HttpHeaders setter;
+
+ @Context
+ public void setSetter(HttpHeaders setter) {
+ this.setter = setter;
+ }
+
+ @Override
+ public Response toResponse(NullPointerException ex) {
+ return Response.status(520)
+ .header("x-test-header", setter.getHeaderString("x-test-header"))
+ .build();
+ }
+}
diff --git a/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestApplication.java b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestApplication.java
new file mode 100644
index 0000000..3102bfa
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestApplication.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/")
+public class TestApplication extends javax.ws.rs.core.Application {
+
+}
diff --git a/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestResource.java b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestResource.java
new file mode 100644
index 0000000..8c18fe6
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/java/org/glassfish/jersey/tests/integration/jersey2988/TestResource.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+
+@Path("/test")
+public class TestResource {
+
+ @Inject
+ private ContextAwareBean contextAwareBean;
+
+ @GET
+ @Path("field")
+ public Response field() {
+ return contextAwareBean.fieldConfig();
+ }
+
+ @GET
+ @Path("setter")
+ public Response setter() {
+ return contextAwareBean.setterConfig();
+ }
+
+ @GET
+ @Path("ex/field")
+ public String fieldExceptionMapper() {
+ throw new IllegalStateException("My handled exception.");
+ }
+
+ @GET
+ @Path("ex/setter")
+ public String setterExceptionMapper() {
+ throw new NullPointerException("My handled exception.");
+ }
+
+}
diff --git a/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/beans.xml b/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..3dcd6e8
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
+ version="1.1" bean-discovery-mode="all">
+
+</beans>
diff --git a/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/jetty-web.xml b/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/jetty-web.xml
new file mode 100644
index 0000000..eb69254
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/main/webapp/WEB-INF/jetty-web.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="serverClasses">
+ <Array type="java.lang.String">
+ <Item>-org.eclipse.jetty.servlet.ServletContextHandler.Decorator</Item>
+ </Array>
+ </Set>
+</Configure>
diff --git a/tests/integration/JERSEY-2988/src/test/java/org/glassfish/jersey/tests/integration/jersey2988/Jersey2988ITCase.java b/tests/integration/JERSEY-2988/src/test/java/org/glassfish/jersey/tests/integration/jersey2988/Jersey2988ITCase.java
new file mode 100644
index 0000000..b5bc49d
--- /dev/null
+++ b/tests/integration/JERSEY-2988/src/test/java/org/glassfish/jersey/tests/integration/jersey2988/Jersey2988ITCase.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2988;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * JERSEY-2988 reproducer and JERSEY-2990 (duplicate of the previous one)
+ *
+ * @author Petr Bouda
+ */
+public class Jersey2988ITCase extends JerseyTest {
+
+ private static final String HEADER_NAME = "x-test-header";
+ private static final String HEADER_VALUE = "cool-header";
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Reproducer for JERSEY-2988
+ *
+ * @throws Exception
+ */
+ @Test
+ public void contextFieldInjection() throws Exception {
+ testCdiBeanContextInjection("field");
+ }
+
+ @Test
+ public void contextSetterInjection() throws Exception {
+ testCdiBeanContextInjection("setter");
+ }
+
+ private void testCdiBeanContextInjection(String path) {
+ int status = target("test/" + path).request().get().getStatus();
+ if (status != 200) {
+ fail("@Context field is not properly injected into CDI Bean.");
+ }
+ }
+
+ /**
+ * Reproducer for JERSEY-2990
+ *
+ * @throws Exception
+ */
+ @Test
+ public void contextFieldInjectionExceptionMapper() throws Exception {
+ testExceptionMapperContextInjection("field");
+ }
+
+ @Test
+ public void contextSetterExceptionMapper() throws Exception {
+ testExceptionMapperContextInjection("setter");
+ }
+
+ private void testExceptionMapperContextInjection(String path) {
+ Response response = target("test/ex/" + path).request().header(HEADER_NAME, HEADER_VALUE).get();
+ if (response.getStatus() != 520 || !HEADER_VALUE.equals(response.getHeaderString(HEADER_NAME))) {
+ fail("@Context method was not properly injected into ExceptionMapper.");
+ }
+ }
+}
diff --git a/tests/integration/async-jersey-filter/pom.xml b/tests/integration/async-jersey-filter/pom.xml
new file mode 100644
index 0000000..da8cd9b
--- /dev/null
+++ b/tests/integration/async-jersey-filter/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>async-jersey-filter</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-async-filter</name>
+
+ <description>
+ This web project reproduces tickets:
+ JERSEY-2730
+ JERSEY-2812
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/async/TestApplication.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/async/TestApplication.java
new file mode 100644
index 0000000..f23fa16
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/async/TestApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.async;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.jersey.tests.integration.jersey2730.TestExceptionResource;
+import org.glassfish.jersey.tests.integration.jersey2730.exception.MappedExceptionMapper;
+import org.glassfish.jersey.tests.integration.jersey2812.TestWaitResource;
+
+/**
+ * Jersey application for JERSEY-2730.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestExceptionResource.class);
+ register(MappedExceptionMapper.class);
+ register(TestWaitResource.class);
+ }
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/TestExceptionResource.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/TestExceptionResource.java
new file mode 100644
index 0000000..c531760
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/TestExceptionResource.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.servlet.internal.ResponseWriter;
+import org.glassfish.jersey.tests.integration.jersey2730.exception.MappedException;
+import org.glassfish.jersey.tests.integration.jersey2730.exception.UnmappedException;
+import org.glassfish.jersey.tests.integration.jersey2730.exception.UnmappedRuntimeException;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/exception")
+@Singleton
+public class TestExceptionResource {
+
+ /**
+ * An instance of thread that was processing a last request to this resource.
+ */
+ private Thread lastProcessingThread;
+
+ @GET
+ @Path("null")
+ public void get(@Suspended final AsyncResponse asyncResponse) {
+ lastProcessingThread = Thread.currentThread();
+ asyncResponse.resume((Throwable) null);
+ }
+
+ @GET
+ @Path("mapped")
+ public void getMappedException(@Suspended final AsyncResponse asyncResponse) {
+ lastProcessingThread = Thread.currentThread();
+ asyncResponse.resume(new MappedException());
+ }
+
+ @GET
+ @Path("unmapped")
+ public void getUnmappedException(@Suspended final AsyncResponse asyncResponse) {
+ lastProcessingThread = Thread.currentThread();
+ asyncResponse.resume(new UnmappedException());
+ }
+
+ @GET
+ @Path("runtime")
+ public void getUnmappedRuntimeException(@Suspended final AsyncResponse asyncResponse) {
+ lastProcessingThread = Thread.currentThread();
+ asyncResponse.resume(new UnmappedRuntimeException());
+ }
+
+ /**
+ * Returns whether a thread that was processing a last request got stuck in {@link ResponseWriter}.
+ * <p/>
+ * Under normal circumstances, the last processing thread should return back to the servlet container
+ * and its pool.
+ * <p/>
+ * May not work when executed in parallel.
+ *
+ * @return
+ */
+ @GET
+ @Path("rpc/lastthreadstuck")
+ public boolean lastThreadStuckRpc() {
+ if (lastProcessingThread == null || Thread.currentThread() == lastProcessingThread) {
+ return false;
+ }
+
+ switch (lastProcessingThread.getState()) {
+ case BLOCKED:
+ case TIMED_WAITING:
+ case WAITING:
+ for (StackTraceElement stackTraceElement : lastProcessingThread.getStackTrace()) {
+ if (ResponseWriter.class.getName().equals(stackTraceElement.getClassName())) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedException.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedException.java
new file mode 100644
index 0000000..cc0ab0f
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730.exception;
+
+/**
+ * This exception will get mapped to a 432 response with the application exception mapper
+ * implemented by {@link MappedExceptionMapper} class.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class MappedException extends Exception {
+
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedExceptionMapper.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedExceptionMapper.java
new file mode 100644
index 0000000..052dbc3
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/MappedExceptionMapper.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730.exception;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+/**
+ * An exception mapper to return 432 error response when a {@link MappedException} is thrown.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class MappedExceptionMapper implements ExceptionMapper<MappedException> {
+
+ @Override
+ public Response toResponse(MappedException exception) {
+ return Response.status(432).build();
+ }
+
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedException.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedException.java
new file mode 100644
index 0000000..751872c
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730.exception;
+
+/**
+ * An exception that will be propagated to the servlet container.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class UnmappedException extends Exception {
+
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedRuntimeException.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedRuntimeException.java
new file mode 100644
index 0000000..d84dc6a
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2730/exception/UnmappedRuntimeException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730.exception;
+
+/**
+ * An exception that will be propagated to the servlet container.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class UnmappedRuntimeException extends RuntimeException {
+
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestFilter.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestFilter.java
new file mode 100644
index 0000000..9fd3cd9
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestFilter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2812;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Logger;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * This servlet filter class provides a means to detect whether Jersey (in servlet filter based setup) properly freed the
+ * server-side thread processing the http request to an async RESTful resource where {@link javax.ws.rs.container.AsyncResponse}
+ * wasn't resumed.
+ * <p/>
+ * Reported as JERSEY-2812.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class TestFilter implements Filter {
+
+ private static final Logger LOGGER = Logger.getLogger(TestFilter.class.getName());
+ public static final String CDL_FINISHED = "CDL-finished";
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+
+ }
+
+ @Override
+ public void doFilter(final ServletRequest servletRequest,
+ final ServletResponse servletResponse,
+ final FilterChain filterChain)
+ throws IOException, ServletException {
+ LOGGER.finest(new Date() + " Thread " + Thread.currentThread().getName() + " is being acquired...");
+
+ final CountDownLatch cdlFinished = new CountDownLatch(1);
+ servletRequest.setAttribute(CDL_FINISHED, cdlFinished);
+
+ filterChain.doFilter(servletRequest, servletResponse);
+
+ // the thread did return from Jersey
+ cdlFinished.countDown();
+
+ LOGGER.finest(new Date() + " Thread " + Thread.currentThread().getName() + " is being released.");
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
diff --git a/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestWaitResource.java b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestWaitResource.java
new file mode 100644
index 0000000..b457107
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/java/org/glassfish/jersey/tests/integration/jersey2812/TestWaitResource.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2812;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotAcceptableException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This resource provides a way to reproduce JERSEY-2818.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/async")
+@Produces("text/plain")
+@Singleton
+public class TestWaitResource {
+
+ private static final Logger LOGGER = Logger.getLogger(TestWaitResource.class.getName());
+
+ /**
+ * Test context identified by UUID chosen by client.
+ */
+ private final ConcurrentMap<String, TestContext> testContextMap = new ConcurrentHashMap<>();
+
+ private TestContext testContextForUUID(String uuid) {
+ testContextMap.putIfAbsent(uuid, new TestContext());
+ return testContextMap.get(uuid);
+ }
+
+ @GET
+ @Path("wait/{uuid}")
+ public void waitForEvent(@Suspended AsyncResponse asyncResponse,
+ @Context HttpServletRequest request,
+ @PathParam("uuid") String uuid) {
+
+ LOGGER.finer("Adding response: " + asyncResponse);
+
+ final TestContext testContext = testContextForUUID(uuid);
+ final CountDownLatch finishedCdl = (CountDownLatch) request.getAttribute(TestFilter.CDL_FINISHED);
+
+ if (finishedCdl == null) {
+ throw new IllegalStateException("The " + TestFilter.class + " was not properly processed before this request!");
+ }
+
+ testContext.asyncResponse = asyncResponse;
+ testContext.finishedCdl = finishedCdl;
+ testContext.startedCdl.countDown();
+
+ LOGGER.finer("Decreasing started cdl: " + testContext.startedCdl);
+ }
+
+ @POST
+ @Path("release/{uuid}")
+ public String releaseLastSuspendedAsyncRequest(@PathParam("uuid") String uuid) {
+
+ LOGGER.finer("Releasing async response");
+
+ if (!testContextMap.containsKey(uuid)) {
+ throw new NotAcceptableException("UUID not found!" + uuid);
+ }
+
+ // clean it up
+ final TestContext releasedTestContext = testContextMap.remove(uuid);
+ releasedTestContext.finishedCdl.countDown();
+ releasedTestContext.startedCdl.countDown();
+ releasedTestContext.asyncResponse.resume("async-OK-" + uuid);
+
+ return "RELEASED";
+ }
+
+ @GET
+ @Path("await/{uuid}/started")
+ public boolean awaitForTheAsyncRequestThreadToStart(@PathParam("uuid") String uuid, @QueryParam("millis") Long millis) {
+ final CountDownLatch startedCdl = testContextForUUID(uuid).startedCdl;
+ try {
+ LOGGER.finer("Checking started cdl: " + startedCdl);
+ return startedCdl.await(millis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Interrupted while waiting for the thread to finish!", e);
+ }
+ }
+
+ @GET
+ @Path("await/{uuid}/finished")
+ public boolean awaitForTheAsyncRequestThreadToFinish(@PathParam("uuid") String uuid, @QueryParam("millis") Long millis) {
+ if (!testContextMap.containsKey(uuid)) {
+ throw new NotAcceptableException("UUID not found!" + uuid);
+ }
+ try {
+ LOGGER.finer("Decreasing finished cdl: " + testContextMap.get(uuid).finishedCdl);
+ return testContextMap.get(uuid).finishedCdl.await(millis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Interrupted while waiting for the thread to finish!", e);
+ }
+ }
+
+ /**
+ * Test context holder class.
+ * <p/>
+ * Holds the information for one test identified by UUID chosen by client.
+ *
+ * @see #testContextMap
+ */
+ private static class TestContext {
+
+ /**
+ * This CDL ensures the server-side thread processing the request to /async/wait/{uuid} has started handling the request.
+ */
+ final CountDownLatch startedCdl = new CountDownLatch(1);
+
+ /**
+ * This CDL ensures the server-side thread processing the request to /async/wait/{uuid} was returned to the thread-pool.
+ */
+ volatile CountDownLatch finishedCdl;
+
+ /**
+ * The async response that does get resumed outside of the request to /async/wait/{uuid}. This reproduces the JERSEY-2812
+ * bug.
+ */
+ volatile AsyncResponse asyncResponse;
+ }
+
+}
diff --git a/tests/integration/async-jersey-filter/src/main/webapp/WEB-INF/web.xml b/tests/integration/async-jersey-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d1d166c
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="true">
+
+ <filter>
+ <filter-name>jersey2812</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.jersey2812.TestFilter</filter-class>
+ <async-supported>true</async-supported>
+ </filter>
+
+ <filter>
+ <filter-name>jersey</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <async-supported>true</async-supported>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.async.TestApplication</param-value>
+ </init-param>
+ <!-- let ServletContainer#doFilter(HttpServletRequest, HttpServletResponse, FilterChain, String, String, String)
+ resolve the response status -->
+ <init-param>
+ <param-name>jersey.config.servlet.filter.forwardOn404</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>jersey2812</filter-name>
+ <url-pattern>/asyncTest/async/wait/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/exceptionTest/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/asyncTest/*</url-pattern>
+ </filter-mapping>
+
+ <absolute-ordering />
+</web-app>
diff --git a/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/async/AbstractAsyncJerseyTest.java b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/async/AbstractAsyncJerseyTest.java
new file mode 100644
index 0000000..a2e1927
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/async/AbstractAsyncJerseyTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.async;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class AbstractAsyncJerseyTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestApplication.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+}
diff --git a/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2730/Jersey2730ITCase.java b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2730/Jersey2730ITCase.java
new file mode 100644
index 0000000..c3ca725
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2730/Jersey2730ITCase.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2730;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.tests.integration.async.AbstractAsyncJerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * JERSEY-2730 reproducer.
+ * <p/>
+ * This test must not run in parallel.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class Jersey2730ITCase extends AbstractAsyncJerseyTest {
+
+ private void assertLastThreadNotStuck() {
+ final boolean lastThreadGotStuck = target("/exceptionTest/exception/rpc/lastthreadstuck").request().get(boolean.class);
+
+ assertFalse("Thread processing last request got stuck while processing the request for "
+ + TestExceptionResource.class.getCanonicalName(),
+ lastThreadGotStuck);
+ }
+
+ @Test
+ public void asyncResourceNullThrowableReturns500AndDoesNotStuck() throws Exception {
+ final Response response = target("/exceptionTest/exception/null").request().get();
+
+ assertEquals(500, response.getStatus());
+ assertLastThreadNotStuck();
+ }
+
+ @Test
+ public void asyncResourceUnmappedExceptionReturns500AndDoesNotStuck() throws Exception {
+ final Response response = target("/exceptionTest/exception/unmapped").request().get();
+
+ assertEquals(500, response.getStatus());
+ assertLastThreadNotStuck();
+ }
+
+ @Test
+ public void asyncResourceUnmappedRuntimeExceptionReturns500AndDoesNotStuck() throws Exception {
+ final Response response = target("/exceptionTest/exception/runtime").request().get();
+
+ assertEquals(500, response.getStatus());
+ assertLastThreadNotStuck();
+ }
+
+ @Test
+ public void asyncResourceMappedExceptionReturns432() throws Exception {
+ final Response response = target("/exceptionTest/exception/mapped").request().get();
+
+ assertEquals(432, response.getStatus());
+ assertLastThreadNotStuck();
+ }
+
+ @Test
+ public void asyncResourceNonExistentReturns404() throws Exception {
+ final Response response = target("/exceptionTest/exception/notfound").request().get();
+
+ assertEquals(404, response.getStatus());
+ }
+
+}
diff --git a/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2812/Jersey2812ITCase.java b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2812/Jersey2812ITCase.java
new file mode 100644
index 0000000..d86a8f4
--- /dev/null
+++ b/tests/integration/async-jersey-filter/src/test/java/org/glassfish/jersey/tests/integration/jersey2812/Jersey2812ITCase.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2812;
+
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.core.Response;
+
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.tests.integration.async.AbstractAsyncJerseyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * JERSEY-2812 reproducer.
+ * <p/>
+ * This test must not run in parallel.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class Jersey2812ITCase extends AbstractAsyncJerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(Jersey2812ITCase.class.getName());
+ private static long WAIT_TIMEOUT = 5000;
+
+ private AtomicReference<String> asyncResult = new AtomicReference<>();
+ private String uuid = UUID.randomUUID().toString();
+ private ExecutorService executorService = Executors
+ .newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(true).build());
+
+ @Before
+ public void triggerTheWaitRequestInSeparateThread() throws Exception {
+ executorService.execute(new Runnable() {
+ @Override
+ public void run() {
+ LOGGER.finer("Running a request to /async/wait in a separate thread.");
+ asyncResult.set(target("/asyncTest/async/wait").path(uuid).request().get(String.class));
+ }
+ });
+ }
+
+ /**
+ * Tests whether the server-side thread that is processing a http request to the servlet-filter-based Jersey setup ends up
+ * stuck or returned back to the pool of available threads.
+ * <p/>
+ * This test prevents a regression reported in JERSEY-2812.
+ * <p/>
+ * When the {@link javax.ws.rs.container.AsyncResponse} was left intact in the RESTful resource (as implemented in {@link
+ * TestWaitResource#waitForEvent(AsyncResponse, HttpServletRequest, String)}), the server-side Jersey thread ended up in
+ * {@link org.glassfish.jersey.servlet.internal.ResponseWriter#getResponseContext()} blocked because of the resolution of http
+ * response status from {@link org.glassfish.jersey.servlet.ServletContainer#doFilter(HttpServletRequest, HttpServletResponse,
+ * FilterChain, String, String, String)}
+ * <p/>
+ * This test uses a separate thread to call {@code /async/wait/{uuid}} resource which blocks until the {@code
+ * /async/release/{uuid}} is called. In the meantime the JUnit thread calls {@code /async/await/{uuid}} to discover whether
+ * the server-side thread processing the request to {@code /async/await/{uuid}/started} did start processing of the request.
+ * Consecutively, the JUnit thread calls {@code /async/await/{uuid}/finished} with a timeout {@code #WAIT_TIMEOUT} to discover
+ * whether the server-side thread got stuck (which is what JERSEY-2812 reported) or not.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void asyncSuspendedResourceDoesNotGetStuck() throws Exception {
+ // [1] wait for the /async/wait request to be processed
+ final Response startResponse = target("/asyncTest/async/await").path(uuid).path("started")
+ .queryParam("millis", WAIT_TIMEOUT).request().get();
+ assertTrue("The server-side thread handling the request to /async/wait didn't start in timely fashion. "
+ + "This error indicates this test is not executed / designed properly rather than a regression in "
+ + "JERSEY-2812 fix.",
+ startResponse.readEntity(Boolean.class));
+
+ // [2] wait for the /async/wait request to finish
+ final Response finishResponse = target("/asyncTest/async/await").path(uuid).path("finished")
+ .queryParam("millis", WAIT_TIMEOUT).request().get();
+ assertTrue("The thread processing the /async/wait request did not respond in timely fashion. "
+ + "Memory leak / thread got stuck detected!",
+ finishResponse.readEntity(Boolean.class));
+
+ // [3] release the blocked http call to /async/wait
+ final String releaseResponse = target("/asyncTest/async/release").path(uuid).request().post(null, String.class);
+ assertEquals("RELEASED", releaseResponse);
+
+ // [4] test whether everything ended as expected
+ executorService.shutdown();
+ assertTrue("The test thread did not finish in timely fashion!",
+ executorService.awaitTermination(WAIT_TIMEOUT, TimeUnit.MILLISECONDS));
+ assertEquals("async-OK-" + uuid, asyncResult.get());
+ }
+
+ @After
+ public void releaseResources() {
+ // release the server-side thread regardless of whether left un-attended
+ target("/asyncTest/async/release").path(uuid).request().post(null);
+ }
+
+ @After
+ public void terminateThread() {
+ // forcibly terminate the test client thread
+ executorService.shutdownNow();
+ }
+
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/pom.xml b/tests/integration/cdi-beanvalidation-webapp/pom.xml
new file mode 100644
index 0000000..df201d3
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-beanvalidation-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-beanvalidation-webapp</name>
+
+ <description>Jersey CDI/Bean Validation test web application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator-cdi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x-validation</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>run-external-tests</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${external.container.factory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${external.container.port}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <!-- External test container configuration is done via properties to allow overriding via command line. -->
+ <external.container.factory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</external.container.factory>
+ <external.container.port>8080</external.container.port>
+ <maven.test.skip>false</maven.test.skip>
+ </properties>
+ </profile>
+ </profiles>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ </build>
+</project>
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiApplication.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiApplication.java
new file mode 100644
index 0000000..6adcc12
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiApplication.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources.
+ * This one is configured as a CDI bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/cdi")
+@ApplicationScoped
+public class CdiApplication extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(CdiFieldInjectedResource.class);
+ add(CdiParamInjectedResource.class);
+ add(CdiPropertyInjectedResource.class);
+ add(CdiOldFashionedResource.class);
+
+ add(CdiValidationInterceptor.class);
+ }};
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiFieldInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiFieldInjectedResource.java
new file mode 100644
index 0000000..31d05cf
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiFieldInjectedResource.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.context.RequestScoped;
+
+import javax.inject.Inject;
+import javax.validation.ConstraintViolationException;
+import javax.validation.constraints.NotNull;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * This CDI backed resource should get validated and validation result field injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/field")
+@RequestScoped
+public class CdiFieldInjectedResource {
+
+ @Inject
+ ValidationResult validationResult;
+
+ @Inject
+ NonJaxRsValidatedBean cdiBean;
+
+ @QueryParam("q")
+ @NotNull
+ String q;
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from field injected validation bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate() {
+
+ return validationResult.getViolationCount();
+ }
+
+ /**
+ * Return number of validation issues for non JAX-RS bean.
+ * This is to make sure the implicit Hibernate validator
+ * is functioning for raw CDI beans, where Jersey
+ * is not involved in method invocation.
+ *
+ * @return number of validation issues revealed when invoking injected CDI bean.
+ */
+ @Path("validate/non-jaxrs")
+ @GET
+ public int getValidateNonJaxRs(@QueryParam("h") String h) {
+
+ try {
+ cdiBean.echo(h);
+ return 0;
+ } catch (ConstraintViolationException ex) {
+ return ex.getConstraintViolations().size();
+ }
+ }
+
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiOldFashionedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiOldFashionedResource.java
new file mode 100644
index 0000000..b7a5803
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiOldFashionedResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.validation.constraints.NotNull;
+
+/**
+ * This CDI backed resource should get validated.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("old/fashioned")
+@RequestScoped
+public class CdiOldFashionedResource {
+
+ /**
+ * Query param getter.
+ *
+ * @return query param value.
+ */
+ @Path("validate")
+ @GET
+ public String getQ(@QueryParam("q") @NotNull String q) {
+
+ return q;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiParamInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiParamInjectedResource.java
new file mode 100644
index 0000000..18f74c7
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiParamInjectedResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.context.RequestScoped;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+
+/**
+ * This CDI backed resource should get validated.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/param")
+@RequestScoped
+public class CdiParamInjectedResource {
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from param injected validation bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate(@QueryParam("q") @NotNull String q, @Context ValidationResult validationResult) {
+
+ return validationResult.getViolationCount();
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiPropertyInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiPropertyInjectedResource.java
new file mode 100644
index 0000000..2af8a87
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiPropertyInjectedResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.Interceptors;
+import javax.interceptor.InvocationContext;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * This CDI backed resource should get validated and validation result property injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/property")
+@RequestScoped
+public class CdiPropertyInjectedResource {
+
+ private ValidationResult validationResult;
+
+ @Inject
+ public void setValidationResult(ValidationResult validationResult) {
+ this.validationResult = validationResult;
+ }
+
+ public ValidationResult getValidationResult() {
+ return validationResult;
+ }
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from field injected validation bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate(@QueryParam("q") @NotNull String q) {
+
+ return getValidationResult().getViolationCount();
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationInterceptor.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationInterceptor.java
new file mode 100644
index 0000000..d3f9d9d
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationInterceptor.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+
+import org.glassfish.jersey.server.spi.ValidationInterceptor;
+import org.glassfish.jersey.server.spi.ValidationInterceptorContext;
+
+import org.jboss.weld.interceptor.util.proxy.TargetInstanceProxy;
+
+/**
+ * CDI backed interceptor to handle validation issues.
+ *
+ * @author Jaku Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+public class CdiValidationInterceptor implements ValidationInterceptor {
+
+ private final CdiValidationResult validationResult;
+ private final CdiPropertyInjectedResource pir;
+
+ /**
+ * Empty constructor to make CDI happy.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public CdiValidationInterceptor() {
+ this.validationResult = null;
+ this.pir = null;
+ }
+
+ /**
+ * Injection constructor.
+ *
+ * @param validationResult CDI implementation of validation result.
+ * @param resource CDI property-injected JAX-RS resource.
+ */
+ @Inject
+ public CdiValidationInterceptor(CdiValidationResult validationResult, CdiPropertyInjectedResource resource) {
+ this.validationResult = validationResult;
+ this.pir = resource;
+ }
+
+ @Override
+ public void onValidate(ValidationInterceptorContext ctx) throws ValidationException {
+
+ final Object resource = ctx.getResource();
+ if (resource instanceof TargetInstanceProxy) {
+ ctx.setResource(((TargetInstanceProxy) resource).getTargetInstance());
+ }
+
+ try {
+ ctx.proceed();
+ } catch (ConstraintViolationException constraintViolationException) {
+
+ // First check for a property
+ if (ValidationResultUtil.hasValidationResultProperty(resource)) {
+ final Method validationResultGetter = ValidationResultUtil.getValidationResultGetter(resource);
+ ValidationResultUtil.updateValidationResultProperty(resource, validationResultGetter,
+ constraintViolationException.getConstraintViolations());
+ pir.setValidationResult(validationResult);
+ } else {
+ // Then check for a field
+ final Field vr = ValidationResultUtil.getValidationResultField(resource);
+ if (vr != null) {
+ // we have the right guy, no need to use reflection:
+ validationResult.setViolations(constraintViolationException.getConstraintViolations());
+ } else {
+ if (isValidationResultInArgs(ctx.getArgs())) {
+ this.validationResult.setViolations(constraintViolationException.getConstraintViolations());
+ } else {
+ throw constraintViolationException;
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isValidationResultInArgs(Object[] args) {
+ for (Object a : args) {
+ if (a != null) {
+ Class<?> argClass = a.getClass();
+ do {
+ if (ValidationResult.class.isAssignableFrom(argClass)) {
+ return true;
+ }
+ argClass = argClass.getSuperclass();
+ } while (argClass != Object.class);
+ }
+ }
+ return false;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResult.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResult.java
new file mode 100644
index 0000000..0bed3ff
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResult.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.RequestScoped;
+import javax.validation.ConstraintViolation;
+
+/**
+ * CDI implementation of validation result.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+public class CdiValidationResult implements ValidationResult {
+
+ private Set<ConstraintViolation<?>> constraintViolationSet;
+
+ public void setViolations(Set<ConstraintViolation<?>> violations) {
+ this.constraintViolationSet = new HashSet<>(violations);
+ }
+
+ @Override
+ public Set<ConstraintViolation<?>> getAllViolations() {
+ return constraintViolationSet;
+ }
+
+ @Override
+ public boolean isFailed() {
+ return (constraintViolationSet != null) ? !constraintViolationSet.isEmpty() : false;
+ }
+
+ @Override
+ public int getViolationCount() {
+ return (constraintViolationSet != null) ? constraintViolationSet.size() : 0;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResultBinder.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResultBinder.java
new file mode 100644
index 0000000..52bdb79
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/CdiValidationResultBinder.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.util.Set;
+
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+
+import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil;
+import org.glassfish.jersey.ext.cdi1x.internal.GenericCdiBeanSupplier;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.server.spi.ComponentProvider;
+
+/**
+ * Utility that binds HK2 factory to provide CDI managed validation result bean.
+ * This is to make sure validation result could be injected as a resource method parameter
+ * even when running in CDI environment.
+ */
+public class CdiValidationResultBinder implements Extension, ComponentProvider {
+
+ @Inject
+ BeanManager beanManager;
+
+ InjectionManager injectionManager;
+
+ @Override
+ public void initialize(InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ this.beanManager = CdiUtil.getBeanManager();
+ }
+
+ @Override
+ public boolean bind(Class<?> component, Set<Class<?>> providerContracts) {
+ return false;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void done() {
+ if (beanManager != null) { // in CDI environment
+ Binding binding = Bindings
+ .supplier(new GenericCdiBeanSupplier(
+ CdiValidationResult.class, injectionManager, beanManager, true))
+ .to(CdiValidationResult.class)
+ .to(ValidationResult.class);
+
+ injectionManager.register(binding);
+ }
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2Application.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2Application.java
new file mode 100644
index 0000000..e6efb11
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2Application.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.ws.rs.ApplicationPath;
+
+import javax.enterprise.inject.Vetoed;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application to configure resources.
+ * This one will get fully managed by HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/hk2")
+@Vetoed
+public class Hk2Application extends ResourceConfig {
+
+ public Hk2Application() {
+ super(Hk2ParamInjectedResource.class,
+ Hk2FieldInjectedResource.class,
+ Hk2PropertyInjectedResource.class,
+ Hk2OldFashionedResource.class);
+
+ register(new Hk2ValidationInterceptor.Binder());
+ register(new AbstractBinder(){
+
+ @Override
+ protected void configure() {
+ bindAsContract(Hk2ValidationResult.class).to(ValidationResult.class).in(RequestScoped.class);
+ }
+ });
+ }
+
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2FieldInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2FieldInjectedResource.java
new file mode 100644
index 0000000..3d3b850
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2FieldInjectedResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.inject.Vetoed;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+
+/**
+ * This one should get validated.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/field")
+@Vetoed
+public class Hk2FieldInjectedResource {
+
+ @QueryParam("q")
+ @NotNull
+ String q;
+
+ @Context
+ ValidationResult validationResult;
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from field produced bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate() {
+ return validationResult.getViolationCount();
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2OldFashionedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2OldFashionedResource.java
new file mode 100644
index 0000000..a1c8596
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2OldFashionedResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.inject.Vetoed;
+import javax.validation.constraints.NotNull;
+
+/**
+ * This HK2 managed resource should get validated.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("old/fashioned")
+@Vetoed
+public class Hk2OldFashionedResource {
+
+ /**
+ * Query param getter.
+ *
+ * @return query parameter value.
+ */
+ @Path("validate")
+ @GET
+ public String getQ(@QueryParam("q") @NotNull String q) {
+
+ return q;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ParamInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ParamInjectedResource.java
new file mode 100644
index 0000000..ee9a6fb
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ParamInjectedResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.inject.Vetoed;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+
+/**
+ * This HK2 managed resource should get validated and validation
+ * result injected via resource method parameter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/param")
+@Vetoed
+public class Hk2ParamInjectedResource {
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from field produced bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate(@QueryParam("q") @NotNull String q, @Context Hk2ValidationResult validationResult) {
+
+ return validationResult.getViolationCount();
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2PropertyInjectedResource.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2PropertyInjectedResource.java
new file mode 100644
index 0000000..ba02b09
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2PropertyInjectedResource.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.inject.Vetoed;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+
+/**
+ * This one should get validated.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("validated/property")
+@Vetoed
+public class Hk2PropertyInjectedResource {
+
+ @QueryParam("q")
+ @NotNull
+ String q;
+
+ ValidationResult validationResult;
+
+ public ValidationResult getValidationResult() {
+ return validationResult;
+ }
+
+ @Context
+ public void setValidationResult(ValidationResult validationResult) {
+ this.validationResult = validationResult;
+ }
+
+ /**
+ * Return number of validation issues.
+ *
+ * @return value from field produced bean.
+ */
+ @Path("validate")
+ @GET
+ public int getValidate() {
+ return validationResult.getViolationCount();
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationInterceptor.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationInterceptor.java
new file mode 100644
index 0000000..985453d
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationInterceptor.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.function.Supplier;
+
+import javax.ws.rs.core.Context;
+
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.spi.ValidationInterceptor;
+import org.glassfish.jersey.server.spi.ValidationInterceptorContext;
+
+/**
+ * HK2 managed validation interceptor.
+ */
+@Vetoed
+public class Hk2ValidationInterceptor implements ValidationInterceptor {
+
+
+ private final Provider<Hk2ValidationResult> validationResult;
+
+ public Hk2ValidationInterceptor(Provider<Hk2ValidationResult> validationResult) {
+ this.validationResult = validationResult;
+ }
+
+ public static class Binder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bindFactory(ValidationInterceptorFactory.class, Singleton.class)
+ .to(ValidationInterceptor.class);
+ }
+
+ }
+
+ private static class ValidationInterceptorFactory implements Supplier<ValidationInterceptor> {
+
+ @Inject
+ Provider<Hk2ValidationResult> validationResultProvider;
+
+ @Override
+ public ValidationInterceptor get() {
+ return new Hk2ValidationInterceptor(validationResultProvider);
+ }
+ }
+
+ @Override
+ public void onValidate(
+ ValidationInterceptorContext ctx) throws ValidationException {
+ try {
+ ctx.proceed();
+ } catch (ConstraintViolationException ex) {
+ ensureValidationResultInjected(ctx, ex);
+ validationResult.get().setViolations(ex.getConstraintViolations());
+ }
+ }
+
+ private void ensureValidationResultInjected(
+ final ValidationInterceptorContext ctx, final ConstraintViolationException ex) {
+
+ if (!isValidationResultInArgs(ctx.getArgs())
+ && !isValidationResultInResource(ctx)
+ && !hasValidationResultProperty(ctx.getResource())) {
+
+ throw ex;
+ }
+ }
+
+ private boolean isValidationResultInResource(ValidationInterceptorContext ctx) {
+ Class<?> clazz = ctx.getResource().getClass();
+ do {
+ for (Field f : clazz.getDeclaredFields()) {
+ // Of ValidationResult and JAX-RS injectable
+ if (ValidationResult.class.isAssignableFrom(f.getType())
+ && f.getAnnotation(Context.class) != null) {
+ return true;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return false;
+ }
+
+ private boolean isValidationResultInArgs(Object[] args) {
+ for (Object a : args) {
+ if (a != null && ValidationResult.class.isAssignableFrom(a.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines if a resource has a property of type {@code javax.mvc.validation.ValidationResult}.
+ *
+ * @param resource resource instance.
+ * @return outcome of test.
+ */
+ public static boolean hasValidationResultProperty(final Object resource) {
+ return getValidationResultGetter(resource) != null && getValidationResultSetter(resource) != null;
+ }
+
+ /**
+ * Returns a getter for {@code javax.mvc.validation.ValidationResult} or {@code null}
+ * if one cannot be found.
+ *
+ * @param resource resource instance.
+ * @return getter or {@code null} if not available.
+ */
+ public static Method getValidationResultGetter(final Object resource) {
+ Class<?> clazz = resource.getClass();
+ do {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (isValidationResultGetter(m)) {
+ return m;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return null;
+ }
+
+ /**
+ * Determines if a method is a getter for {@code javax.mvc.validation.ValidationResult}.
+ *
+ * @param m method to test.
+ * @return outcome of test.
+ */
+ private static boolean isValidationResultGetter(Method m) {
+ return m.getName().startsWith("get")
+ && ValidationResult.class.isAssignableFrom(m.getReturnType())
+ && Modifier.isPublic(m.getModifiers()) && m.getParameterTypes().length == 0;
+ }
+
+ /**
+ * Returns a setter for {@code javax.mvc.validation.ValidationResult} or {@code null}
+ * if one cannot be found.
+ *
+ * @param resource resource instance.
+ * @return setter or {@code null} if not available.
+ */
+ public static Method getValidationResultSetter(final Object resource) {
+ Class<?> clazz = resource.getClass();
+ do {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (isValidationResultSetter(m)) {
+ return m;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return null;
+ }
+
+ /**
+ * Determines if a method is a setter for {@code javax.mvc.validation.ValidationResult}.
+ * As a CDI initializer method, it must be annotated with {@link javax.inject.Inject}.
+ *
+ * @param m method to test.
+ * @return outcome of test.
+ */
+ private static boolean isValidationResultSetter(Method m) {
+ return m.getName().startsWith("set") && m.getParameterTypes().length == 1
+ && ValidationResult.class.isAssignableFrom(m.getParameterTypes()[0])
+ && m.getReturnType() == Void.TYPE && Modifier.isPublic(m.getModifiers())
+ && m.getAnnotation(Context.class) != null;
+ }
+
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationResult.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationResult.java
new file mode 100644
index 0000000..f286105
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/Hk2ValidationResult.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.inject.Vetoed;
+import javax.validation.ConstraintViolation;
+
+/**
+ * HK2 managed validation result bean.
+ */
+@Vetoed
+public class Hk2ValidationResult implements ValidationResult {
+
+ Set<ConstraintViolation<?>> constraintViolationSet;
+
+ public void setViolations(Set<ConstraintViolation<?>> violations) {
+ this.constraintViolationSet = new HashSet<>(violations);
+ }
+
+ @Override
+ public Set<ConstraintViolation<?>> getAllViolations() {
+ return constraintViolationSet;
+ }
+
+ @Override
+ public boolean isFailed() {
+ return (constraintViolationSet != null) ? !constraintViolationSet.isEmpty() : false;
+ }
+
+ @Override
+ public int getViolationCount() {
+ return (constraintViolationSet != null) ? constraintViolationSet.size() : 0;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/NonJaxRsValidatedBean.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/NonJaxRsValidatedBean.java
new file mode 100644
index 0000000..110aca3
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/NonJaxRsValidatedBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.enterprise.context.RequestScoped;
+import javax.validation.constraints.NotNull;
+
+/**
+ * CDI bean that gets validated by Hibernate validator directly.
+ * This is to ensure Jersey interceptor wrapper
+ * does not block the original validator from functioning
+ * on raw CDI beans.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+public class NonJaxRsValidatedBean {
+
+ public String echo(@NotNull String value) {
+ return value;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResult.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResult.java
new file mode 100644
index 0000000..b723793
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResult.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+
+/**
+ * An interface to be utilized when resource method validation issues
+ * are to be handled within actual resource method.
+ */
+public interface ValidationResult {
+
+ /**
+ * Returns an immutable set of all constraint violations detected.
+ *
+ * @return All constraint violations detected
+ */
+ public Set<ConstraintViolation<?>> getAllViolations();
+
+ /**
+ * Returns <code>true</code> if there is at least one constraint violation.
+ * Same as checking whether {@link #getViolationCount()} is greater than zero.
+ *
+ * @return <code>true</code> if there is at least one constraint violation.
+ */
+ public boolean isFailed();
+
+ /**
+ * Returns the total number of constraint violations detected. Same as calling
+ * <code>getAllViolations().size()</code>.
+ *
+ * @return The number of constraint violations
+ */
+ int getViolationCount();
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResultUtil.java b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResultUtil.java
new file mode 100644
index 0000000..906da13
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/java/org/glassfish/jersey/tests/cdi/bv/ValidationResultUtil.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Set;
+
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.validation.ConstraintViolation;
+
+/**
+ * Helper class to implement support for {@code javax.mvc.validation.ValidationResult}.
+ *
+ * @author Santiago Pericas-Geertsen
+ */
+@Vetoed
+public final class ValidationResultUtil {
+
+ private static final String VALIDATION_RESULT = ValidationResult.class.getName();
+
+ private ValidationResultUtil() {
+ throw new AssertionError("Instantiation not allowed.");
+ }
+
+ /**
+ * Search for a {@code javax.mvc.validation.ValidationResult} field in the resource's
+ * class hierarchy. Field must be annotated with {@link javax.inject.Inject}.
+ *
+ * @param resource resource instance.
+ * @return field or {@code null} if none is found.
+ */
+ public static Field getValidationResultField(final Object resource) {
+ Class<?> clazz = resource.getClass();
+ do {
+ for (Field f : clazz.getDeclaredFields()) {
+ // Of ValidationResult and CDI injectable
+ if (f.getType().getName().equals(VALIDATION_RESULT)
+ && f.getAnnotation(Inject.class) != null) {
+ return f;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return null;
+ }
+
+ /**
+ * Updates a {@code javax.mvc.validation.ValidationResult} field. In pseudo-code:
+ * <p/>
+ * resource.field.setViolations(constraints)
+ *
+ * @param resource resource instance.
+ * @param field field to be updated.
+ * @param constraints new set of constraints.
+ */
+ public static void updateValidationResultField(Object resource, Field field,
+ Set<ConstraintViolation<?>> constraints) {
+ try {
+ field.setAccessible(true);
+ final Object obj = field.get(resource);
+ Method setter;
+ try {
+ setter = obj.getClass().getMethod("setViolations", Set.class);
+ } catch (NoSuchMethodException e) {
+ setter = obj.getClass().getSuperclass().getMethod("setViolations", Set.class);
+ }
+ setter.invoke(obj, constraints);
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ // ignore for now
+ System.out.println("Damn it...");
+ } catch (Throwable t) {
+ System.out.println("What the heck...");
+ }
+ }
+
+ /**
+ * Updates a {@code javax.mvc.validation.ValidationResult} property. In pseudo-code:
+ * <p/>
+ * obj = getter.invoke(resource);
+ * obj.setViolations(constraints);
+ * setter.invoke(resource, obj);
+ *
+ * @param resource resource instance.
+ * @param getter getter to be used.
+ * @param constraints new set of constraints.
+ */
+ public static void updateValidationResultProperty(Object resource, Method getter,
+ Set<ConstraintViolation<?>> constraints) {
+ try {
+ final Object obj = getter.invoke(resource);
+ Method setViolations;
+ try {
+ setViolations = obj.getClass().getMethod("setViolations", Set.class);
+ } catch (NoSuchMethodException e) {
+ setViolations = obj.getClass().getSuperclass().getMethod("setViolations", Set.class);
+ }
+ setViolations.invoke(obj, constraints);
+
+ final Method setter = getValidationResultSetter(resource);
+
+ if (setter != null) {
+ setter.invoke(resource, obj);
+ }
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ // ignore for now
+ }
+ }
+
+ /**
+ * Determines if a resource has a property of type {@code javax.mvc.validation.ValidationResult}.
+ *
+ * @param resource resource instance.
+ * @return outcome of test.
+ */
+ public static boolean hasValidationResultProperty(final Object resource) {
+ return getValidationResultGetter(resource) != null && getValidationResultSetter(resource) != null;
+ }
+
+ /**
+ * Returns a getter for {@code javax.mvc.validation.ValidationResult} or {@code null}
+ * if one cannot be found.
+ *
+ * @param resource resource instance.
+ * @return getter or {@code null} if not available.
+ */
+ public static Method getValidationResultGetter(final Object resource) {
+ Class<?> clazz = resource.getClass();
+ do {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (isValidationResultGetter(m)) {
+ return m;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return null;
+ }
+
+ /**
+ * Determines if a method is a getter for {@code javax.mvc.validation.ValidationResult}.
+ *
+ * @param m method to test.
+ * @return outcome of test.
+ */
+ private static boolean isValidationResultGetter(Method m) {
+ return m.getName().startsWith("get")
+ && m.getReturnType().getName().equals(VALIDATION_RESULT)
+ && Modifier.isPublic(m.getModifiers()) && m.getParameterTypes().length == 0;
+ }
+
+ /**
+ * Returns a setter for {@code javax.mvc.validation.ValidationResult} or {@code null}
+ * if one cannot be found.
+ *
+ * @param resource resource instance.
+ * @return setter or {@code null} if not available.
+ */
+ public static Method getValidationResultSetter(final Object resource) {
+ return getValidationResultSetter(resource.getClass());
+ }
+
+ private static Method getValidationResultSetter(final Class<?> resourceClass) {
+ Class<?> clazz = resourceClass;
+ do {
+ for (Method m : clazz.getDeclaredMethods()) {
+ if (isValidationResultSetter(m)) {
+ return m;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class);
+ return null;
+ }
+
+ /**
+ * Determines if a method is a setter for {@code javax.mvc.validation.ValidationResult}.
+ * As a CDI initializer method, it must be annotated with {@link javax.inject.Inject}.
+ *
+ * @param m method to test.
+ * @return outcome of test.
+ */
+ private static boolean isValidationResultSetter(Method m) {
+ return m.getName().startsWith("set") && m.getParameterTypes().length == 1
+ && m.getParameterTypes()[0].getName().equals(VALIDATION_RESULT)
+ && m.getReturnType() == Void.TYPE && Modifier.isPublic(m.getModifiers())
+ && m.getAnnotation(Inject.class) != null;
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..d036d62
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.bv.CdiValidationResultBinder
\ No newline at end of file
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
new file mode 100644
index 0000000..d036d62
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.bv.CdiValidationResultBinder
\ No newline at end of file
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-beanvalidation-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..1d9cc6c
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
+
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/BaseValidationTest.java b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/BaseValidationTest.java
new file mode 100644
index 0000000..f2eb3fb
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/BaseValidationTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Common test for resource validation. The same set of tests is used
+ * for the following scenarios: Grizzly based combined deployment with CDI enabled,
+ * WAR based combined deployment with CDI enabled, Grizzly based deployment without CDI enabled.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public abstract class BaseValidationTest extends JerseyTest {
+
+ public abstract String getAppPath();
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-beanvalidation-webapp").path(getAppPath()).build();
+ }
+
+ @Test
+ public void testParamValidatedResourceNoParam() throws Exception {
+ _testParamValidatedResourceNoParam(target());
+ }
+
+ public static void _testParamValidatedResourceNoParam(final WebTarget target) throws Exception {
+
+ Integer errors = target.register(LoggingFeature.class)
+ .path("validated").path("param").path("validate")
+ .request().get(Integer.class);
+
+ assertThat(errors, is(1));
+ }
+
+ @Test
+ public void testParamValidatedResourceParamProvided() throws Exception {
+ _testParamValidatedResourceParamProvided(target());
+ }
+
+ public static void _testParamValidatedResourceParamProvided(WebTarget target) throws Exception {
+ Integer errors = target.register(LoggingFeature.class).path("validated").path("field").path("validate")
+ .queryParam("q", "one").request().get(Integer.class);
+ assertThat(errors, is(0));
+ }
+
+ @Test
+ public void testFieldValidatedResourceNoParam() throws Exception {
+ _testFieldValidatedResourceNoParam(target());
+ }
+
+ public static void _testFieldValidatedResourceNoParam(final WebTarget target) throws Exception {
+
+ Integer errors = target.register(LoggingFeature.class)
+ .path("validated").path("field").path("validate")
+ .request().get(Integer.class);
+
+ assertThat(errors, is(1));
+ }
+
+ @Test
+ public void testFieldValidatedResourceParamProvided() throws Exception {
+ _testFieldValidatedResourceParamProvided(target());
+ }
+
+ public static void _testFieldValidatedResourceParamProvided(final WebTarget target) throws Exception {
+ Integer errors = target.register(LoggingFeature.class).path("validated").path("field").path("validate")
+ .queryParam("q", "one").request().get(Integer.class);
+ assertThat(errors, is(0));
+ }
+
+ @Test
+ public void testPropertyValidatedResourceNoParam() throws Exception {
+ _testPropertyValidatedResourceNoParam(target());
+ }
+
+ public static void _testPropertyValidatedResourceNoParam(final WebTarget target) throws Exception {
+
+ Integer errors = target.register(LoggingFeature.class)
+ .path("validated").path("property").path("validate")
+ .request().get(Integer.class);
+
+ assertThat(errors, is(1));
+ }
+
+ @Test
+ public void testPropertyValidatedResourceParamProvided() throws Exception {
+ _testPropertyValidatedResourceParamProvided(target());
+ }
+
+ public static void _testPropertyValidatedResourceParamProvided(final WebTarget target) throws Exception {
+ Integer errors = target.register(LoggingFeature.class).path("validated").path("property").path("validate")
+ .queryParam("q", "one").request().get(Integer.class);
+ assertThat(errors, is(0));
+ }
+
+ @Test
+ public void testOldFashionedResourceNoParam() {
+ _testOldFashionedResourceNoParam(target());
+ }
+
+ public static void _testOldFashionedResourceNoParam(final WebTarget target) {
+
+ Response response = target.register(LoggingFeature.class)
+ .path("old").path("fashioned").path("validate")
+ .request().get();
+
+ assertThat(response.getStatus(), is(400));
+ }
+
+ @Test
+ public void testOldFashionedResourceParamProvided() throws Exception {
+ _testOldFashionedResourceParamProvided(target());
+ }
+
+ public static void _testOldFashionedResourceParamProvided(final WebTarget target) throws Exception {
+ String response = target.register(LoggingFeature.class).path("old").path("fashioned").path("validate")
+ .queryParam("q", "one").request().get(String.class);
+ assertThat(response, is("one"));
+ }
+
+ public static void _testNonJaxRsValidationFieldValidatedResourceNoParam(final WebTarget target) {
+ Integer errors = target.register(LoggingFeature.class)
+ .path("validated").path("field").path("validate").path("non-jaxrs")
+ .queryParam("q", "not-important-just-to-get-this-through-jax-rs").request().get(Integer.class);
+
+ assertThat(errors, is(1));
+ }
+
+ public static void _testNonJaxRsValidationFieldValidatedResourceParamProvided(final WebTarget target) {
+ Integer errors = target.register(LoggingFeature.class)
+ .path("validated").path("field").path("validate").path("non-jaxrs")
+ .queryParam("q", "not-important-just-to-get-this-through-jax-rs")
+ .queryParam("h", "bummer")
+ .request().get(Integer.class);
+
+ assertThat(errors, is(0));
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/CombinedTest.java b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/CombinedTest.java
new file mode 100644
index 0000000..847b0ef
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/CombinedTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Properties;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainerProvider;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.glassfish.grizzly.http.server.HttpHandler;
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.hamcrest.CoreMatchers;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test both Jersey apps running simultaneously within a single Grizzly HTTP server
+ * to make sure injection managers do not interfere. The test is not executed
+ * if other than the default (Grizzly) test container has been set.
+ * For Servlet based container testing, the other two tests, {@link RawCdiTest} and {@link RawHk2Test},
+ * do the same job, because the WAR application contains both Jersey apps already.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CombinedTest {
+
+ public static final String CDI_URI = "/cdi";
+ public static final String HK2_URI = "/hk2";
+
+ public static final String PORT_NUMBER = getSystemProperty(TestProperties.CONTAINER_PORT,
+ Integer.toString(TestProperties.DEFAULT_CONTAINER_PORT));
+
+ private static final URI BASE_HK2_URI = URI.create("http://localhost:" + PORT_NUMBER + HK2_URI);
+ private static final URI BASE_CDI_URI = URI.create("http://localhost:" + PORT_NUMBER + CDI_URI);
+
+ private static final boolean isDefaultTestContainerFactorySet = isDefaultTestContainerFactorySet();
+
+ Weld weld;
+ HttpServer cdiServer;
+
+ Client client;
+ WebTarget cdiTarget, hk2Target;
+
+ @Before
+ public void before() throws IOException {
+ if (isDefaultTestContainerFactorySet && Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ initializeWeld();
+ startGrizzlyContainer();
+ initializeClient();
+ }
+ }
+
+ @Before
+ public void beforeIsImmediate() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @After
+ public void after() {
+ if (isDefaultTestContainerFactorySet && Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ cdiServer.shutdownNow();
+ weld.shutdown();
+ client.close();
+ }
+ }
+
+ @Test
+ public void testParamValidatedResourceNoParam() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testParamValidatedResourceNoParam(cdiTarget);
+ BaseValidationTest._testParamValidatedResourceNoParam(hk2Target);
+ }
+
+ @Test
+ public void testParamValidatedResourceParamProvided() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testParamValidatedResourceParamProvided(cdiTarget);
+ BaseValidationTest._testParamValidatedResourceParamProvided(hk2Target);
+ }
+
+ @Test
+ public void testFieldValidatedResourceNoParam() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testFieldValidatedResourceNoParam(cdiTarget);
+ BaseValidationTest._testFieldValidatedResourceNoParam(hk2Target);
+ }
+
+ @Test
+ public void testFieldValidatedResourceParamProvided() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testFieldValidatedResourceParamProvided(cdiTarget);
+ BaseValidationTest._testFieldValidatedResourceParamProvided(hk2Target);
+ }
+
+ @Test
+ public void testPropertyValidatedResourceNoParam() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testPropertyValidatedResourceNoParam(cdiTarget);
+ BaseValidationTest._testPropertyValidatedResourceNoParam(hk2Target);
+ }
+
+ @Test
+ public void testPropertyValidatedResourceParamProvided() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testPropertyValidatedResourceParamProvided(cdiTarget);
+ BaseValidationTest._testPropertyValidatedResourceParamProvided(hk2Target);
+ }
+
+ @Test
+ public void testOldFashionedResourceNoParam() {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testOldFashionedResourceNoParam(cdiTarget);
+ BaseValidationTest._testOldFashionedResourceNoParam(hk2Target);
+ }
+
+ @Test
+ public void testOldFashionedResourceParamProvided() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testOldFashionedResourceParamProvided(cdiTarget);
+ BaseValidationTest._testOldFashionedResourceParamProvided(hk2Target);
+ }
+
+ @Test
+ public void testNonJaxRsValidationFieldValidatedResourceNoParam() {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testNonJaxRsValidationFieldValidatedResourceNoParam(cdiTarget);
+ }
+
+ @Test
+ public void testNonJaxRsValidationFieldValidatedResourceParamProvided() {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ BaseValidationTest._testNonJaxRsValidationFieldValidatedResourceParamProvided(cdiTarget);
+ }
+
+ private void initializeWeld() {
+ weld = new Weld();
+ weld.initialize();
+ }
+
+ private void startGrizzlyContainer() throws IOException {
+ final ResourceConfig cdiConfig = ResourceConfig.forApplicationClass(CdiApplication.class);
+ final ResourceConfig hk2Config = ResourceConfig.forApplicationClass(Hk2Application.class);
+
+ cdiServer = GrizzlyHttpServerFactory.createHttpServer(BASE_CDI_URI, cdiConfig, false);
+ final HttpHandler hk2Handler = createGrizzlyContainer(hk2Config);
+ cdiServer.getServerConfiguration().addHttpHandler(hk2Handler, HK2_URI);
+ cdiServer.start();
+ }
+
+ private void initializeClient() {
+ client = ClientBuilder.newClient();
+ cdiTarget = client.target(BASE_CDI_URI);
+ hk2Target = client.target(BASE_HK2_URI);
+ }
+
+ private GrizzlyHttpContainer createGrizzlyContainer(ResourceConfig resourceConfig) {
+ return (new GrizzlyHttpContainerProvider()).createContainer(GrizzlyHttpContainer.class, resourceConfig);
+ }
+
+ private static boolean isDefaultTestContainerFactorySet() {
+ final String testContainerFactory = getSystemProperty(TestProperties.CONTAINER_FACTORY, null);
+ return testContainerFactory == null || TestProperties.DEFAULT_CONTAINER_FACTORY.equals(testContainerFactory);
+ }
+
+ private static String getSystemProperty(final String propertyName, final String defaultValue) {
+ final Properties systemProperties = System.getProperties();
+ return systemProperties.getProperty(propertyName, defaultValue);
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawCdiTest.java b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawCdiTest.java
new file mode 100644
index 0000000..d0b996c
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawCdiTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * Validation result test for CDI environment.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class RawCdiTest extends BaseValidationTest {
+
+ Weld weld;
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) {
+ weld = new Weld();
+ weld.initialize();
+ }
+ super.setUp();
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) {
+ weld.shutdown();
+ }
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return ResourceConfig.forApplicationClass(CdiApplication.class);
+ }
+
+ @Override
+ public String getAppPath() {
+ return "cdi";
+ }
+
+ @Test
+ public void testNonJaxRsValidationFieldValidatedResourceNoParam() {
+ BaseValidationTest._testNonJaxRsValidationFieldValidatedResourceNoParam(target());
+ }
+
+ @Test
+ public void testNonJaxRsValidationFieldValidatedResourceParamProvided() {
+ BaseValidationTest._testNonJaxRsValidationFieldValidatedResourceParamProvided(target());
+ }
+}
diff --git a/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawHk2Test.java b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawHk2Test.java
new file mode 100644
index 0000000..f83ea61
--- /dev/null
+++ b/tests/integration/cdi-beanvalidation-webapp/src/test/java/org/glassfish/jersey/tests/cdi/bv/RawHk2Test.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.bv;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Validation result test for raw HK2 environment.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class RawHk2Test extends BaseValidationTest {
+
+ @Override
+ protected Application configure() {
+ return ResourceConfig.forApplicationClass(Hk2Application.class);
+ }
+
+ @Override
+ public String getAppPath() {
+ return "hk2";
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/pom.xml b/tests/integration/cdi-ejb-test-webapp/pom.xml
new file mode 100644
index 0000000..39b0521
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-ejb-test-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-ejb-webapp</name>
+
+ <description>Jersey CDI/EJB test web application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/BasicTimer.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/BasicTimer.java
new file mode 100644
index 0000000..775fae0
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/BasicTimer.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * Basic timer implementation to be reused for various types of beans.
+ *
+ * @author Jakub Podlesak
+ */
+public abstract class BasicTimer {
+
+ long ms;
+
+ /**
+ * Provide information on internal timer millisecond value.
+ *
+ * @return milliseconds when the current bean has been post-constructed.
+ */
+ public long getMiliseconds() {
+ return ms;
+ }
+
+ /**
+ * Initialize this timer with the current time.
+ */
+ @PostConstruct
+ public void init() {
+ this.ms = System.currentTimeMillis();
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiAppScopedTimer.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiAppScopedTimer.java
new file mode 100644
index 0000000..259e669
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiAppScopedTimer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Application scoped CDI bean to be injected into EJB resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+public class CdiAppScopedTimer extends BasicTimer {
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedResource.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedResource.java
new file mode 100644
index 0000000..a2e6204
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.EJB;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * Request scoped CDI bean injected with EJB timers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-scoped")
+public class CdiRequestScopedResource {
+
+ @EJB EjbSingletonTimer ejbInjectedTimer;
+ @Inject EjbSingletonTimer jsr330InjectedTimer;
+ @Inject CdiAppScopedTimer cdiTimer;
+
+ @GET
+ @Path("ejb-injected-timer")
+ public String getEjbTime() {
+ return Long.toString(ejbInjectedTimer.getMiliseconds());
+ }
+
+ @GET
+ @Path("jsr330-injected-timer")
+ public String getJsr330Time() {
+ return Long.toString(jsr330InjectedTimer.getMiliseconds());
+ }
+
+ @GET
+ public String getMyself() {
+ return this.toString();
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedTimer.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedTimer.java
new file mode 100644
index 0000000..f48e1f4
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiRequestScopedTimer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Request scoped CDI timer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+public class CdiRequestScopedTimer extends BasicTimer {
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonResource.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonResource.java
new file mode 100644
index 0000000..b3472d9
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.Singleton;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * EJB singleton session bean injected with CDI timers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+@Path("singleton")
+public class EjbSingletonResource {
+
+ @Inject CdiRequestScopedTimer requestScopedTimer;
+ @Inject CdiAppScopedTimer appScopedTimer;
+
+ @GET
+ @Path("request-scoped-timer")
+ public String getReqTime() {
+ return Long.toString(requestScopedTimer.getMiliseconds());
+ }
+
+ @GET
+ @Path("app-scoped-timer")
+ public String getAppTime() {
+ return Long.toString(appScopedTimer.getMiliseconds());
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonTimer.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonTimer.java
new file mode 100644
index 0000000..3bec04d
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbSingletonTimer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.Singleton;
+
+/**
+ * EJB singleton timer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+public class EjbSingletonTimer extends BasicTimer {
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatefulResource.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatefulResource.java
new file mode 100644
index 0000000..25fbc9f
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatefulResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.Stateful;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * EJB backed JAX-RS resource injected with CDI service providers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateful
+@Path("stateful")
+public class EjbStatefulResource {
+
+ @Inject CdiRequestScopedTimer requestScopedTimer;
+ @Inject CdiAppScopedTimer appScopedTimer;
+
+ @GET
+ @Path("request-scoped-timer")
+ public String getReqTime() {
+ return Long.toString(requestScopedTimer.getMiliseconds());
+ }
+
+ @GET
+ @Path("app-scoped-timer")
+ public String getAppTime() {
+ return Long.toString(appScopedTimer.getMiliseconds());
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessResource.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessResource.java
new file mode 100644
index 0000000..71da1ce
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * EJB session bean injected with CDI service providers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("stateless")
+public class EjbStatelessResource {
+
+ @Inject CdiRequestScopedTimer requestScopedTimer;
+ @Inject CdiAppScopedTimer appScopedTimer;
+
+ @GET
+ @Path("request-scoped-timer")
+ public String getReqTime() {
+ return Long.toString(requestScopedTimer.getMiliseconds());
+ }
+
+ @GET
+ @Path("app-scoped-timer")
+ public String getAppTime() {
+ return Long.toString(appScopedTimer.getMiliseconds());
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessTimer.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessTimer.java
new file mode 100644
index 0000000..721aa18
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EjbStatelessTimer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ejb.Stateless;
+
+/**
+ * EJB session timer bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+public class EjbStatelessTimer extends BasicTimer {
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..69e395d
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(CdiRequestScopedResource.class);
+ classes.add(CdiRequestScopedTimer.class);
+ classes.add(CdiAppScopedTimer.class);
+ classes.add(EjbStatelessResource.class);
+ classes.add(EjbStatefulResource.class);
+ classes.add(EjbSingletonResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..71e6b6e
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+</web-app>
diff --git a/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiIntoEjbTest.java b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiIntoEjbTest.java
new file mode 100644
index 0000000..d0e8226
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiIntoEjbTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test CDI timers injected into EJB beans.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiIntoEjbTest extends TestBase {
+
+ @Test
+ public void testStateless() {
+ _testRequestScoped("stateless");
+ _testAppScoped("stateless");
+ }
+
+ @Test
+ public void testStateful() {
+ _testRequestScoped("stateful");
+ _testAppScoped("stateful");
+ }
+
+ @Test
+ public void testSingleton() {
+ _testRequestScoped("singleton");
+ _testAppScoped("singleton");
+ }
+
+ private void _testRequestScoped(final String ejbType) {
+
+ final WebTarget target = target().path(ejbType).path("request-scoped-timer");
+ long firstMillis = _getMillis(target);
+ sleep(2);
+ long secondMillis = _getMillis(target);
+
+ assertTrue("Second request should have greater millis!", secondMillis > firstMillis);
+ }
+
+ private void _testAppScoped(final String ejbType) {
+
+ final WebTarget target = target().path(ejbType).path("app-scoped-timer");
+ long firstMillis = _getMillis(target);
+ sleep(2);
+ long secondMillis = _getMillis(target);
+
+ assertTrue("Second request should have the same millis!", secondMillis == firstMillis);
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EjbIntoCdiTest.java b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EjbIntoCdiTest.java
new file mode 100644
index 0000000..231836c
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EjbIntoCdiTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.equalTo;
+
+/**
+ * Test EJB timers injected into CDI beans.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EjbIntoCdiTest extends TestBase {
+
+ @Test
+ public void testInjection() {
+
+ final WebTarget cdiResource = target().path("request-scoped");
+ final WebTarget ejbInjectedTimer = cdiResource.path("ejb-injected-timer");
+ final WebTarget jsr330InjectedTimer = cdiResource.path("jsr330-injected-timer");
+
+ String firstResource = cdiResource.request().get(String.class);
+ long firstMillis = _getMillis(ejbInjectedTimer);
+ sleep(2);
+ String secondResource = cdiResource.request().get(String.class);
+ long secondMillis = _getMillis(jsr330InjectedTimer);
+
+ assertThat(firstMillis, equalTo(secondMillis));
+ assertThat(firstResource, not(equalTo(secondResource)));
+ }
+}
diff --git a/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TestBase.java b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TestBase.java
new file mode 100644
index 0000000..d11189d
--- /dev/null
+++ b/tests/integration/cdi-ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TestBase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-test-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class TestBase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-ejb-test-webapp").build();
+ }
+
+ protected long _getMillis(final WebTarget target) throws NumberFormatException {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ return Long.decode(response.readEntity(String.class));
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(CdiIntoEjbTest.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+}
+
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
new file mode 100644
index 0000000..d0cf29f
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-iface-with-non-jaxrs-impl-test-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-iface-with-non-jaxrs-impl-test-webapp</name>
+
+ <description>Jersey CDI using non JAX-RS implementation for CDI injection</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiEcho.java b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiEcho.java
new file mode 100644
index 0000000..217a999
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiEcho.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Raw CDI implementation of {@link Echo} service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiEcho implements Echo {
+
+ @Override
+ public String echo(String s) {
+ return String.format("CDI ECHOED %s", s);
+ }
+}
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Echo.java b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Echo.java
new file mode 100644
index 0000000..0173d6c
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Echo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Echo service interface.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface Echo {
+
+ /**
+ * Echo service method;
+ *
+ * @param s input
+ * @return echoed input
+ */
+ public String echo(String s);
+}
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java
new file mode 100644
index 0000000..5ca0c7c
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * JAX-RS resource class backed by CDI bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("echo")
+public class EchoResource {
+
+ // CDI injection, HK2 should back off
+ // even if EchoImpl is not directly used here
+ // and could appear as HK2 custom bound type
+ // to Jersey CDI extension
+ @Inject Echo echoService;
+
+ @GET
+ public String cdiEcho(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+}
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..a5506a8
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<>();
+ classes.add(EchoResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..71e6b6e
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+</web-app>
diff --git a/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EchoResourceTest.java b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EchoResourceTest.java
new file mode 100644
index 0000000..dfe58b0
--- /dev/null
+++ b/tests/integration/cdi-iface-with-non-jaxrs-impl-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/EchoResourceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.startsWith;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-test-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EchoResourceTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-iface-with-non-jaxrs-impl-test-webapp").build();
+ }
+
+ @Test
+ public void testCdiInjection() throws Exception {
+ final Response response = target().path("echo").queryParam("s", "I").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), startsWith("CDI ECHOED"));
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(EchoResourceTest.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+}
diff --git a/tests/integration/cdi-multimodule/ear/pom.xml b/tests/integration/cdi-multimodule/ear/pom.xml
new file mode 100644
index 0000000..5b01d1e
--- /dev/null
+++ b/tests/integration/cdi-multimodule/ear/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>cdi-multimodule-ear</artifactId>
+ <packaging>ear</packaging>
+ <name>jersey-tests-integration-cdi-multimodule-ear</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
+ <modules>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-war1</artifactId>
+ </webModule>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-war2</artifactId>
+ </webModule>
+ <jarModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-lib</artifactId>
+ </jarModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-war1</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-war2</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>cdi-multimodule-lib</artifactId>
+ <type>jar</type>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/integration/cdi-multimodule/lib/pom.xml b/tests/integration/cdi-multimodule/lib/pom.xml
new file mode 100644
index 0000000..4e38c98
--- /dev/null
+++ b/tests/integration/cdi-multimodule/lib/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>cdi-multimodule-lib</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-integration-cdi-multimodule-lib</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedDependentBean.java b/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedDependentBean.java
new file mode 100644
index 0000000..44eca4a
--- /dev/null
+++ b/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedDependentBean.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.lib;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * CDI managed bean, that gets JAX-RS injected. This bean is being consumed
+ * by all web apps within an EAR packaged enterprise application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsInjectedDependentBean {
+
+ @Context
+ UriInfo uriInfo;
+
+ @HeaderParam("x-test")
+ String testHeader;
+
+ /**
+ * Get me URI info.
+ *
+ * @return URI info from the JAX-RS layer.
+ */
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ /**
+ * Get me the actual request test header.
+ *
+ * @return actual request URI info.
+ */
+ public String getTestHeader() {
+ return testHeader;
+ }
+
+}
diff --git a/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedRequestScopedBean.java b/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedRequestScopedBean.java
new file mode 100644
index 0000000..5664ed8
--- /dev/null
+++ b/tests/integration/cdi-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/lib/JaxRsInjectedRequestScopedBean.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.lib;
+
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * CDI managed bean, that gets JAX-RS injected. This bean is being consumed
+ * by all web apps within an EAR packaged enterprise application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+public class JaxRsInjectedRequestScopedBean {
+
+ @Context
+ UriInfo uriInfo;
+
+ @HeaderParam("x-test")
+ String testHeader;
+
+ /**
+ * Get me the actual JAX-RS request URI info.
+ *
+ * @return actual request URI info.
+ */
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ /**
+ * Get me the actual request test header.
+ *
+ * @return actual request URI info.
+ */
+ public String getTestHeader() {
+ return testHeader;
+ }
+}
diff --git a/tests/integration/cdi-multimodule/lib/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-multimodule/lib/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..3b46d69
--- /dev/null
+++ b/tests/integration/cdi-multimodule/lib/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-multimodule/pom.xml b/tests/integration/cdi-multimodule/pom.xml
new file mode 100644
index 0000000..803f972
--- /dev/null
+++ b/tests/integration/cdi-multimodule/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-multimodule</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration-cdi-multimodule</name>
+
+ <description>
+ CDI Multi-Module
+ </description>
+
+ <modules>
+ <module>ear</module>
+ <module>lib</module>
+ <module>war1</module>
+ <module>war2</module>
+ </modules>
+</project>
diff --git a/tests/integration/cdi-multimodule/war1/pom.xml b/tests/integration/cdi-multimodule/war1/pom.xml
new file mode 100644
index 0000000..6c9cea8
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>cdi-multimodule-war1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-cdi-multimodule-war</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>cdi-multimodule-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/AppScopedJaxRsResource.java b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/AppScopedJaxRsResource.java
new file mode 100644
index 0000000..3a1a69c
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/AppScopedJaxRsResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web1;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedDependentBean;
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedRequestScopedBean;
+
+/**
+ * JAX-RS resource backed by an application scoped CDI bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("app-scoped")
+@ApplicationScoped
+public class AppScopedJaxRsResource {
+
+ @Inject
+ JaxRsInjectedRequestScopedBean reqScopedBean;
+
+ @Path("req/header")
+ @GET
+ public String getReqHeader() {
+ return reqScopedBean.getTestHeader();
+ }
+
+ @Path("req/uri/{p}")
+ @GET
+ public String getReqUri() {
+ return reqScopedBean.getUriInfo().getRequestUri().toString();
+ }
+
+}
diff --git a/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsApp.java b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsApp.java
new file mode 100644
index 0000000..f8b64da
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsApp.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web1;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application resource configuration.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/")
+public class JaxRsApp extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(RequestScopedJaxRsResource.class);
+ add(AppScopedJaxRsResource.class);
+ }};
+ }
+}
diff --git a/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/RequestScopedJaxRsResource.java b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/RequestScopedJaxRsResource.java
new file mode 100644
index 0000000..5f0ff3e
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/RequestScopedJaxRsResource.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web1;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedDependentBean;
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedRequestScopedBean;
+
+/**
+ * JAX-RS resource backed by a request scoped CDI bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("request-scoped")
+@RequestScoped
+public class RequestScopedJaxRsResource {
+
+ @Inject
+ JaxRsInjectedDependentBean dependentBean;
+
+ @Inject
+ JaxRsInjectedRequestScopedBean reqScopedBean;
+
+ @Path("req/header")
+ @GET
+ public String getReqHeader() {
+ return reqScopedBean.getTestHeader();
+ }
+
+ @Path("dependent/header")
+ @GET
+ public String getDependentHeader() {
+ return dependentBean.getTestHeader();
+ }
+
+ @Path("req/uri/{p}")
+ @GET
+ public String getReqUri() {
+ return reqScopedBean.getUriInfo().getRequestUri().toString();
+ }
+
+ @Path("dependent/uri/{p}")
+ @GET
+ public String getAppUri() {
+ return dependentBean.getUriInfo().getRequestUri().toString();
+ }
+}
diff --git a/tests/integration/cdi-multimodule/war1/src/main/webapp/index.jsp b/tests/integration/cdi-multimodule/war1/src/main/webapp/index.jsp
new file mode 100644
index 0000000..d9c02e5
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/src/main/webapp/index.jsp
@@ -0,0 +1,31 @@
+<%--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JSP Page</title>
+ </head>
+ <body>
+ <h1>Hello World!</h1>
+ </body>
+</html>
diff --git a/tests/integration/cdi-multimodule/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsCdiIntegrationTest.java b/tests/integration/cdi-multimodule/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsCdiIntegrationTest.java
new file mode 100644
index 0000000..62cf293
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web1/JaxRsCdiIntegrationTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web1;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test for CDI web application resources. The JAX-RS resources use CDI components from a library jar.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsCdiIntegrationTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApp();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-multimodule-war1").build();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testUriInfoInjectionReqScopedResourceDependentBean() {
+ _testResource("request-scoped/dependent");
+ }
+
+ @Test
+ public void testUriInfoInjectionReqScopedResourceRequestScopedBean() {
+ _testResource("request-scoped/req");
+ }
+
+ @Test
+ public void testUriInfoInjectionAppScopedResourceRequestScopedBean() {
+ _testResource("app-scoped/req");
+ }
+
+ private void _testResource(String resourcePath) {
+ _testUriInfo(resourcePath);
+ _testHeader(resourcePath);
+ }
+
+ private void _testUriInfo(String resourcePath) {
+
+ _testSinglePathUriUnfo(resourcePath, "one");
+ _testSinglePathUriUnfo(resourcePath, "two");
+ _testSinglePathUriUnfo(resourcePath, "three");
+ }
+
+ private void _testSinglePathUriUnfo(final String resourcePath, final String pathParam) {
+
+ final URI baseUri = getBaseUri();
+ final String expectedResult = baseUri.resolve(resourcePath + "/uri/" + pathParam).toString();
+
+ final Response response = target().path(resourcePath).path("uri").path(pathParam).request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+
+ private void _testHeader(final String resourcePath) {
+
+ _testSingleHeader(resourcePath, "one");
+ _testSingleHeader(resourcePath, "two");
+ _testSingleHeader(resourcePath, "three");
+ }
+
+ private void _testSingleHeader(final String resourcePath, final String headerValue) {
+
+ final String expectedResult = headerValue;
+
+ final Response response = target().path(resourcePath).path("header").request().header("x-test", headerValue).get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+}
diff --git a/tests/integration/cdi-multimodule/war2/pom.xml b/tests/integration/cdi-multimodule/war2/pom.xml
new file mode 100644
index 0000000..0c4352b
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>cdi-multimodule-war2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-cdi-multimodule-war2</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>cdi-multimodule-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppOne.java b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppOne.java
new file mode 100644
index 0000000..11d5cb3
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppOne.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web2;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * First JAX-RS application resource configuration.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("one")
+public class JaxRsAppOne extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(SharedRequestScopedJaxRsResource.class);
+ add(SharedAppScopedJaxRsResource.class);
+ }};
+ }
+}
+
diff --git a/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppTwo.java b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppTwo.java
new file mode 100644
index 0000000..0dbe770
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsAppTwo.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web2;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Second JAX-RS application resource configuration.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("two")
+public class JaxRsAppTwo extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(SharedRequestScopedJaxRsResource.class);
+ add(SharedAppScopedJaxRsResource.class);
+ }};
+ }
+}
+
diff --git a/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedAppScopedJaxRsResource.java b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedAppScopedJaxRsResource.java
new file mode 100644
index 0000000..ba722b7
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedAppScopedJaxRsResource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web2;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedDependentBean;
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedRequestScopedBean;
+
+/**
+ * JAX-RS resource backed by an application scoped CDI bean.
+ * This one is being shared between the two JAX-RS apps
+ * {@link JaxRsAppOne} and {@link JaxRsAppTwo}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("app-scoped")
+@ApplicationScoped
+public class SharedAppScopedJaxRsResource {
+
+ @Inject
+ JaxRsInjectedDependentBean dependentBean;
+
+ @Inject
+ JaxRsInjectedRequestScopedBean reqScopedBean;
+
+ @Path("req/header")
+ @GET
+ public String getReqHeader() {
+ return reqScopedBean.getTestHeader();
+ }
+
+ @Path("dependent/header")
+ @GET
+ public String getDependentHeader() {
+ return dependentBean.getTestHeader();
+ }
+
+ @Path("req/uri/{p}")
+ @GET
+ public String getReqUri() {
+ return reqScopedBean.getUriInfo().getRequestUri().toString();
+ }
+
+ @Path("dependent/uri/{p}")
+ @GET
+ public String getAppUri() {
+ return dependentBean.getUriInfo().getRequestUri().toString();
+ }
+}
diff --git a/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedRequestScopedJaxRsResource.java b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedRequestScopedJaxRsResource.java
new file mode 100644
index 0000000..876ee7f
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/SharedRequestScopedJaxRsResource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web2;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedDependentBean;
+import org.glassfish.jersey.tests.integration.multimodule.cdi.lib.JaxRsInjectedRequestScopedBean;
+
+/**
+ * JAX-RS resource backed by a request scoped CDI bean.
+ * This one is being shared between the two JAX-RS apps
+ * {@link JaxRsAppOne} and {@link JaxRsAppTwo}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("request-scoped")
+@RequestScoped
+public class SharedRequestScopedJaxRsResource {
+
+ @Inject
+ JaxRsInjectedDependentBean dependentBean;
+
+ @Inject
+ JaxRsInjectedRequestScopedBean reqScopedBean;
+
+ @Path("req/header")
+ @GET
+ public String getReqHeader() {
+ return reqScopedBean.getTestHeader();
+ }
+
+ @Path("dependent/header")
+ @GET
+ public String getDependentHeader() {
+ return dependentBean.getTestHeader();
+ }
+
+ @Path("req/uri/{p}")
+ @GET
+ public String getReqUri() {
+ return reqScopedBean.getUriInfo().getRequestUri().toString();
+ }
+
+ @Path("dependent/uri/{p}")
+ @GET
+ public String getAppUri() {
+ return dependentBean.getUriInfo().getRequestUri().toString();
+ }
+}
diff --git a/tests/integration/cdi-multimodule/war2/src/main/webapp/index.jsp b/tests/integration/cdi-multimodule/war2/src/main/webapp/index.jsp
new file mode 100644
index 0000000..d9c02e5
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/main/webapp/index.jsp
@@ -0,0 +1,31 @@
+<%--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JSP Page</title>
+ </head>
+ <body>
+ <h1>Hello World!</h1>
+ </body>
+</html>
diff --git a/tests/integration/cdi-multimodule/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsCdiIntegrationTest.java b/tests/integration/cdi-multimodule/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsCdiIntegrationTest.java
new file mode 100644
index 0000000..033f953
--- /dev/null
+++ b/tests/integration/cdi-multimodule/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/cdi/web2/JaxRsCdiIntegrationTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.cdi.web2;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test for CDI web application resources. The JAX-RS resources use CDI components from a library jar.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsCdiIntegrationTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsAppOne();
+ }
+
+// @Override
+// protected URI getBaseUri() {
+// return UriBuilder.fromUri(super.getBaseUri()).path("cdi-multimodule-war1").build();
+// }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testUriInfoInjectionReqScopedResourceDependentBean() {
+
+ _testResource("cdi-multimodule-war2/one/request-scoped/dependent");
+ _testResource("cdi-multimodule-war2/two/request-scoped/dependent");
+ }
+
+ @Test
+ public void testUriInfoInjectionReqScopedResourceRequestScopedBean() {
+
+ _testResource("cdi-multimodule-war2/one/request-scoped/req");
+ _testResource("cdi-multimodule-war2/two/request-scoped/req");
+ }
+
+ @Test
+ public void testUriInfoInjectionAppScopedResourceRequestScopedBean() {
+
+ _testResource("cdi-multimodule-war2/one/app-scoped/req");
+ _testResource("cdi-multimodule-war2/two/app-scoped/req");
+ }
+
+ @Ignore("until JERSEY-2914 gets resolved")
+ @Test
+ public void testUriInfoInjectionAppScopedResourceDependentBean() {
+
+ _testResource("cdi-multimodule-war2/one/app-scoped/dependent");
+ _testResource("cdi-multimodule-war2/two/app-scoped/dependent");
+ }
+
+ private void _testResource(String resourcePath) {
+ _testUriInfo(resourcePath);
+ _testHeader(resourcePath);
+ }
+
+ private void _testUriInfo(String resourcePath) {
+
+ _testSinglePathUriUnfo(resourcePath, "one");
+ _testSinglePathUriUnfo(resourcePath, "two");
+ _testSinglePathUriUnfo(resourcePath, "three");
+ }
+
+ private void _testSinglePathUriUnfo(final String resourcePath, final String pathParam) {
+
+ final URI baseUri = getBaseUri();
+ final String expectedResult = baseUri.resolve(resourcePath + "/uri/" + pathParam).toString();
+
+ final Response response = target().path(resourcePath).path("uri").path(pathParam).request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+
+ private void _testHeader(final String resourcePath) {
+
+ _testSingleHeader(resourcePath, "one");
+ _testSingleHeader(resourcePath, "two");
+ _testSingleHeader(resourcePath, "three");
+ }
+
+ private void _testSingleHeader(final String resourcePath, final String headerValue) {
+
+ final String expectedResult = headerValue;
+
+ final Response response = target().path(resourcePath).path("header").request().header("x-test", headerValue).get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+}
diff --git a/tests/integration/cdi-multipart-webapp/pom.xml b/tests/integration/cdi-multipart-webapp/pom.xml
new file mode 100644
index 0000000..79f0bf4
--- /dev/null
+++ b/tests/integration/cdi-multipart-webapp/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-multipart-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-multipart-webapp</name>
+
+ <description>Jersey CDI test web application that uses multipart feature</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java b/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java
new file mode 100644
index 0000000..d64a263
--- /dev/null
+++ b/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoResource.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+
+/**
+ * GF-21033 reproducer. Just a resource using multi-part support.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/echo")
+@RequestScoped
+public class EchoResource {
+
+ /**
+ * We want to consume form data using multi-part provider.
+ *
+ * @param input form data
+ * @return input data
+ */
+ @POST
+ public Response echoMultipart(@FormDataParam ("input") String input) {
+ return Response.ok(input).build();
+ }
+}
diff --git a/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..e730754
--- /dev/null
+++ b/tests/integration/cdi-multipart-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+
+/**
+ * GF-21033 reproducer. This is to make sure Jersey's multipart
+ * feature could work in GF with CDI.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends Application {
+
+ static final Set<Class<?>> classes = new HashSet<Class<?>>();
+
+ static {
+ classes.add(EchoResource.class);
+ classes.add(MultiPartFeature.class);
+ }
+ @Override
+ public Set<Class<?>> getClasses() {
+ return classes;
+ }
+}
diff --git a/tests/integration/cdi-multipart-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-multipart-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..aaf0547
--- /dev/null
+++ b/tests/integration/cdi-multipart-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-multipart-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MultipartFeatureTest.java b/tests/integration/cdi-multipart-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MultipartFeatureTest.java
new file mode 100644
index 0000000..5fb1185
--- /dev/null
+++ b/tests/integration/cdi-multipart-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MultipartFeatureTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Part of GF-21033 reproducer. Make sure form data processed by the Jersey multi-part
+ * feature make it forth and back all right.
+ *
+ * <p/>Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-test-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class MultipartFeatureTest extends JerseyTest {
+
+ final String TestFormDATA;
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"No matter what"},
+ {"You should never"},
+ {"ever"},
+ {"just give up"}
+ });
+ }
+
+ public MultipartFeatureTest(String TestFormDATA) {
+ this.TestFormDATA = TestFormDATA;
+ }
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-multipart-webapp").build();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(MultiPartFeature.class);
+ }
+
+ @Test
+ public void testPostFormData() {
+
+ final WebTarget target = target().path("echo");
+
+ FormDataMultiPart formData = new FormDataMultiPart().field("input", TestFormDATA);
+
+ final Response response = target.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE));
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(TestFormDATA));
+ }
+}
+
diff --git a/tests/integration/cdi-test-webapp/pom.xml b/tests/integration/cdi-test-webapp/pom.xml
new file mode 100644
index 0000000..bfddb0f
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-test-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-webapp</name>
+
+ <description>Jersey CDI test web application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>run-external-tests</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${external.container.factory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${external.container.port}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <!-- External test container configuration is done via properties to allow overriding via command line. -->
+ <external.container.factory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</external.container.factory>
+ <external.container.port>8080</external.container.port>
+ <maven.test.skip>false</maven.test.skip>
+ </properties>
+ </profile>
+ </profiles>
+</project>
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectedResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectedResource.java
new file mode 100644
index 0000000..736dfb9
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectedResource.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+/**
+ * JERSEY-2526 reproducer. CDI managed JAX-RS root resource
+ * that is constructor injected with JAX-RS parameters provided by Jersey
+ * and a single String parameter coming from application provided CDI producer,
+ * {@link CustomCdiProducer}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("ctor-injected/{p}")
+@RequestScoped
+public class ConstructorInjectedResource {
+
+ String pathParam;
+ String queryParam;
+ String matrixParam;
+ String headerParam;
+ String cdiParam;
+
+ /**
+ * WLS requires this.
+ */
+ public ConstructorInjectedResource() {
+ }
+
+ /**
+ * This will get CDI injected with JAX-RS provided parameters.
+ *
+ * @param pathParam path parameter from the actual request.
+ * @param queryParam query parameter q from the actual request.
+ * @param matrixParam matrix parameter m from the actual request.
+ * @param headerParam Accept header parameter from the actual request.
+ * @param cdiParam custom CDI produced string.
+ */
+ @Inject
+ public ConstructorInjectedResource(
+ @PathParam("p") String pathParam,
+ @QueryParam("q") String queryParam,
+ @MatrixParam("m") String matrixParam,
+ @HeaderParam("Custom-Header") String headerParam,
+ @CustomCdiProducer.Qualifier String cdiParam) {
+
+ this.pathParam = pathParam;
+ this.queryParam = queryParam;
+ this.matrixParam = matrixParam;
+ this.headerParam = headerParam;
+ this.cdiParam = cdiParam;
+ }
+
+ /**
+ * Provide string representation of a single injected parameter
+ * given by the actual path parameter (that is also injected).
+ *
+ * @return a single parameter value.
+ */
+ @GET
+ public String getParameter() {
+
+ switch (pathParam) {
+
+ case "pathParam": return pathParam;
+ case "queryParam": return queryParam;
+ case "matrixParam": return matrixParam;
+ case "headerParam": return headerParam;
+ case "cdiParam": return cdiParam;
+
+ default: throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CounterResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CounterResource.java
new file mode 100644
index 0000000..8342a0c
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CounterResource.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * Part of JERSEY-2461 reproducer. This one will get injected with a CDI extension.
+ * HK2 should not mess up with this.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("counter")
+public class CounterResource {
+
+ final CustomExtension e;
+
+ /**
+ * To make CDI happy... namely to make the bean proxy-able.
+ */
+ public CounterResource() {
+ this.e = null;
+ }
+
+ /**
+ * This one will get used at runtime actually.
+ *
+ * @param extension current application CDI custom extension.
+ */
+ @Inject
+ public CounterResource(CustomExtension extension) {
+ this.e = extension;
+ }
+
+ /**
+ * Return custom extension counter state.
+ *
+ * @return next count.
+ */
+ @GET
+ public int getCount() {
+ return e.getCount();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomCdiProducer.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomCdiProducer.java
new file mode 100644
index 0000000..9f00838
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomCdiProducer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.enterprise.inject.Produces;
+
+/**
+ * CDI producer to help us make sure HK2 do not mess up with
+ * types backed by CDI producers.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomCdiProducer {
+
+ /**
+ * Custom qualifier to work around https://java.net/jira/browse/GLASSFISH-20285
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
+ @javax.inject.Qualifier
+ public static @interface Qualifier {
+ }
+
+ /**
+ * To cover field producer.
+ */
+ @Produces
+ public static FieldProducedBean<String> field = new FieldProducedBean<>("field");
+
+ /**
+ * To cover method producer.
+ *
+ * @return bean instance to inject
+ */
+ @Produces
+ public MethodProducedBean<String> produceBean() {
+ return new MethodProducedBean<>("method");
+ }
+
+ /**
+ * Part of JERSEY-2526 reproducer. This one is used
+ * to inject constructor of {@link ConstructorInjectedResource}.
+ *
+ * @return fixed string value.
+ */
+ @Produces
+ @Qualifier
+ public String produceString() {
+ return "cdi-produced";
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomExtension.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomExtension.java
new file mode 100644
index 0000000..081bc51
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CustomExtension.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.enterprise.inject.spi.Extension;
+
+/**
+ * Part of JERSEY-2461 reproducer. We need an extension that we could inject,
+ * to make sure HK2 custom binding does not attempt to mess up.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomExtension implements Extension {
+
+ private AtomicInteger counter = new AtomicInteger();
+
+ /**
+ * A made up functionality. Does not really matter. CDI
+ * would refuse to deploy the application if something went wrong.
+ *
+ * @return next count.
+ */
+ public int getCount() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
new file mode 100644
index 0000000..287d734
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Qualifier;
+
+/**
+ * Simple echo service to test injections using {@link Qualifier}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface EchoService {
+
+ /**
+ * Provide an echoed response.
+ *
+ * @param s String to be echoed.
+ * @return echoed input.
+ */
+ public String echo(String s);
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FieldProducedBean.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FieldProducedBean.java
new file mode 100644
index 0000000..2dbb6c4
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FieldProducedBean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.inject.Vetoed;
+
+/**
+ * A bean that would be produced by a CDI producer field.
+ * This is to make sure we do not mess up with CDI producers with HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Vetoed
+public class FieldProducedBean<T> implements ValueHolder<T> {
+
+ private final T value;
+
+ /**
+ * Make an instance with given value.
+ *
+ * @param value
+ */
+ public FieldProducedBean(T value) {
+ this.value = value;
+ }
+
+ @Override
+ public T getValue() {
+ return value;
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FirstNonJaxRsBeanInjectedResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FirstNonJaxRsBeanInjectedResource.java
new file mode 100644
index 0000000..60b552e
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/FirstNonJaxRsBeanInjectedResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * JAX-RS resource that gets injected with a CDI managed bean,
+ * that includes JAX-RS injection points. The very same bean
+ * gets injected also to {@link FirstNonJaxRsBeanInjectedResource}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("non-jaxrs-bean-injected")
+@RequestScoped
+public class FirstNonJaxRsBeanInjectedResource {
+
+ @Inject
+ JaxRsInjectedBean bean;
+
+ @GET
+ @Path("path/1")
+ public String getPath() {
+ return bean.getUriInfo().getPath();
+ }
+
+ @GET
+ @Path("header/1")
+ public String getAcceptHeader() {
+ return bean.getTestHeader();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentExceptionMapper.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentExceptionMapper.java
new file mode 100644
index 0000000..390dc97
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentExceptionMapper.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import javax.annotation.ManagedBean;
+import javax.annotation.PostConstruct;
+
+/**
+ * JAX-RS exception mapper registered as a CDI managed bean.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@ManagedBean
+public class JCDIBeanDependentExceptionMapper implements ExceptionMapper<JDCIBeanDependentException> {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanDependentExceptionMapper.class.getName());
+
+ @Context
+ private UriInfo uiFieldInject;
+
+ @Context
+ private ResourceContext resourceContext;
+
+ private UriInfo uiMethodInject;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ LOGGER.log(Level.INFO, String.format("In post construct of %s", this));
+ ensureInjected();
+ }
+
+ @Override
+ public Response toResponse(JDCIBeanDependentException exception) {
+ ensureInjected();
+ return Response.serverError().entity("JDCIBeanDependentException").build();
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldInject == null || uiMethodInject == null || resourceContext == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentPerRequestResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentPerRequestResource.java
new file mode 100644
index 0000000..2a36eff
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentPerRequestResource.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.annotation.ManagedBean;
+import javax.annotation.Resource;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.RequestScoped;
+
+
+/**
+ * Request scoped JAX-RS resource registered as a CDI managed bean.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/jcdibean/dependent/per-request")
+@ManagedBean
+@RequestScoped
+public class JCDIBeanDependentPerRequestResource {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanDependentPerRequestResource.class.getName());
+
+ @Resource(name = "injectedResource")
+ private int injectedResource = 0;
+
+ @Context
+ private UriInfo uiFieldInject;
+
+ @Context
+ private ResourceContext rc;
+
+ @QueryParam("x")
+ private String x;
+
+ private UriInfo uiMethodInject;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+
+ ensureInjected();
+
+ LOGGER.info(String.format(
+ "In post construct of %s; uiFieldInject: %s; uiMethodInject: %s",
+ this, uiFieldInject, uiMethodInject));
+ }
+
+ @GET
+ @Produces("text/plain")
+ public String getMessage() {
+
+ ensureInjected();
+
+ LOGGER.info(String.format(
+ "In getMessage of %s; uiFieldInject: %s; uiMethodInject: %s",
+ this, uiFieldInject, uiMethodInject));
+
+ return String.format("%s: queryParam=%s %d", uiFieldInject.getRequestUri().toString(), x, injectedResource++);
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOGGER.info(String.format("In pre destroy of %s", this));
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldInject == null || uiMethodInject == null || rc == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentResource.java
new file mode 100644
index 0000000..589de49
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test case for JERSEY-1747.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/jcdibean/dependent/timer")
+public class JCDIBeanDependentResource {
+
+ @Inject
+ JCDIBeanRequestScopedTimer timer;
+
+ @GET
+ @Produces("text/plain")
+ public String getValue() {
+ return Long.toString(timer.getMiliseconds());
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentSingletonResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentSingletonResource.java
new file mode 100644
index 0000000..09ecf81
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanDependentSingletonResource.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.annotation.ManagedBean;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Application scoped JAX-RS resource registered as CDI managed bean.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/jcdibean/dependent/singleton/{p}")
+@ApplicationScoped
+@ManagedBean
+public class JCDIBeanDependentSingletonResource {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanDependentSingletonResource.class.getName());
+
+ @Resource(name = "injectedResource")
+ private int counter = 0;
+
+ @Context
+ private UriInfo uiFieldinject;
+
+ @Context
+ private ResourceContext resourceContext;
+
+ private UriInfo uiMethodInject;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ LOGGER.info(String.format("In post construct of %s", this));
+ ensureInjected();
+ }
+
+ @GET
+ @Produces("text/plain")
+ public String getMessage(@PathParam("p") String p) {
+ LOGGER.info(String.format(
+ "In getMessage in %s; uiFieldInject: %s; uiMethodInject: %s", this, uiFieldinject, uiMethodInject));
+ ensureInjected();
+
+ return String.format("%s: p=%s, queryParam=%s",
+ uiFieldinject.getRequestUri().toString(), p, uiMethodInject.getQueryParameters().getFirst("x"));
+ }
+
+ @Path("exception")
+ public String getException() {
+ throw new JDCIBeanDependentException();
+ }
+
+ @Path("counter")
+ @GET
+ public synchronized String getCounter() {
+ return Integer.toString(counter++);
+ }
+
+ @Path("counter")
+ @PUT
+ public synchronized void setCounter(String counter) {
+ this.counter = Integer.decode(counter);
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOGGER.info(String.format("In pre destroy of %s", this));
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldinject == null || uiMethodInject == null || resourceContext == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanExceptionMapper.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanExceptionMapper.java
new file mode 100644
index 0000000..d6a06ed
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanExceptionMapper.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * JAX-RS exception mapper registered as CDI managed bean.
+ *
+ * @author Paul Sandoz
+ */
+@Provider
+@ApplicationScoped
+public class JCDIBeanExceptionMapper implements ExceptionMapper<JDCIBeanException> {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanExceptionMapper.class.getName());
+
+ @Context
+ private UriInfo uiFieldInject;
+
+ @Context
+ private ResourceContext rc;
+
+ private UriInfo uiMethodInject;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ ensureInjected();
+ LOGGER.info(String.format("In post construct of %s", this));
+ }
+
+ @Override
+ public Response toResponse(JDCIBeanException exception) {
+ ensureInjected();
+ return Response.serverError().entity("JDCIBeanException").build();
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldInject == null || uiMethodInject == null || rc == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanPerRequestResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanPerRequestResource.java
new file mode 100644
index 0000000..303e9ad
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanPerRequestResource.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Request scoped JAX-RS resource registered.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/jcdibean/per-request")
+@RequestScoped
+public class JCDIBeanPerRequestResource {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanPerRequestResource.class.getName());
+
+ @Resource(name = "injectedResource")
+ private int injectedResource = 0;
+
+ @Context
+ private UriInfo uiFieldInject;
+
+ @Context
+ private ResourceContext rc;
+
+ @QueryParam("x")
+ private String x;
+
+ private UriInfo uiMethodInject;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+
+ ensureInjected();
+
+ LOGGER.info(String.format(
+ "In post construct of %s; uiFieldInject: %s; uiMethodInject: %s",
+ this, uiFieldInject, uiMethodInject));
+ }
+
+ @GET
+ @Produces("text/plain")
+ public String getMessage() {
+
+ ensureInjected();
+
+ LOGGER.info(String.format(
+ "In getMessage of %s; uiFieldInject: %s; uiMethodInject: %s",
+ this, uiFieldInject, uiMethodInject));
+
+ return String.format("%s: queryParam=%s %d", uiFieldInject.getRequestUri().toString(), x, injectedResource++);
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOGGER.info(String.format("In pre destroy of %s", this));
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldInject == null || uiMethodInject == null || rc == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanRequestScopedTimer.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanRequestScopedTimer.java
new file mode 100644
index 0000000..019f5a5
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanRequestScopedTimer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Request scoped CDI bean to be injected into {@link JCDIBeanDependentResource}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+public class JCDIBeanRequestScopedTimer {
+
+ private long ms;
+
+ /**
+ * Provide information on actual request time.
+ *
+ * @return milliseconds when the current bean was post-constructed.
+ */
+ public long getMiliseconds() {
+ return ms;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.ms = System.currentTimeMillis();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanSingletonResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanSingletonResource.java
new file mode 100644
index 0000000..a181f4f
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JCDIBeanSingletonResource.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+/**
+ * Application scoped JAX-RS resource.
+ *
+ * @author Paul Sandoz
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/jcdibean/singleton/{p}")
+@ApplicationScoped
+public class JCDIBeanSingletonResource {
+
+ private static final Logger LOGGER = Logger.getLogger(JCDIBeanSingletonResource.class.getName());
+
+ @Resource(name = "injectedResource")
+ private int counter = 0;
+
+ @Context
+ private UriInfo uiFieldinject;
+
+ @Context
+ private
+ ResourceContext resourceContext;
+
+ private UriInfo uiMethodInject;
+
+ @Inject
+ Provider<JCDIBeanExceptionMapper> mapperProvider;
+
+ @Context
+ public void set(UriInfo ui) {
+ this.uiMethodInject = ui;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ LOGGER.info(String.format("In post construct of %s", this));
+ ensureInjected();
+ }
+
+ @GET
+ @Produces("text/plain")
+ public String getMessage(@PathParam("p") String p) {
+ LOGGER.info(String.format(
+ "In getMessage in %s; uiFieldInject: %s; uiMethodInject: %s; provider: %s; provider.get(): %s", this,
+ uiFieldinject, uiMethodInject, mapperProvider, mapperProvider.get()));
+ ensureInjected();
+
+ return String.format("%s: p=%s, queryParam=%s",
+ uiFieldinject.getRequestUri().toString(), p, uiMethodInject.getQueryParameters().getFirst("x"));
+ }
+
+ @Path("exception")
+ public String getException() {
+ throw new JDCIBeanException();
+ }
+
+ @Path("counter")
+ @GET
+ public synchronized String getCounter() {
+ return Integer.toString(counter++);
+ }
+
+ @Path("counter")
+ @PUT
+ public synchronized void setCounter(String counter) {
+ this.counter = Integer.decode(counter);
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOGGER.info(String.format("In pre destroy of %s", this));
+ }
+
+ private void ensureInjected() throws IllegalStateException {
+ if (uiFieldinject == null || uiMethodInject == null
+ || resourceContext == null || mapperProvider.get() == null) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanDependentException.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanDependentException.java
new file mode 100644
index 0000000..73e837a
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanDependentException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Exception to be treated by {@link JCDIBeanDependentExceptionMapper}.
+ *
+ * @author Paul Sandoz
+ */
+public class JDCIBeanDependentException extends RuntimeException {
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanException.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanException.java
new file mode 100644
index 0000000..2b80a0c
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JDCIBeanException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Exception to be treated by {@link JCDIBeanExceptionMapper}.
+ *
+ * @author Paul Sandoz
+ */
+public class JDCIBeanException extends RuntimeException {
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedBean.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedBean.java
new file mode 100644
index 0000000..fd7a884
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedBean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * This is to be JAX-RS injected at runtime.
+ * The bean is fully CDI managed, contains JAX-RS injection points and is getting injected into JAX-RS
+ * resources included in two distinct JAX-RS applications running in parallel.
+ */
+@RequestScoped
+public class JaxRsInjectedBean {
+
+ @HeaderParam("x-test")
+ String testHeader;
+
+ @Context
+ UriInfo uriInfo;
+
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ public String getTestHeader() {
+ return testHeader;
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MainApplication.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MainApplication.java
new file mode 100644
index 0000000..b6ec0e6
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MainApplication.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+
+import javax.inject.Inject;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jonathan Benoit (jonathan.benoit at oracle.com)
+ */
+@ApplicationPath("main")
+@ApplicationScoped
+public class MainApplication extends Application {
+
+ static AtomicInteger postConstructCounter = new AtomicInteger();
+
+ @Inject BeanManager bm;
+
+ private static final Logger LOGGER = Logger.getLogger(MainApplication.class.getName());
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(JCDIBeanDependentResource.class);
+ classes.add(JDCIBeanException.class);
+ classes.add(JDCIBeanDependentException.class);
+ classes.add(JCDIBeanSingletonResource.class);
+ classes.add(JCDIBeanPerRequestResource.class);
+ classes.add(JCDIBeanExceptionMapper.class);
+ classes.add(JCDIBeanDependentSingletonResource.class);
+ classes.add(JCDIBeanDependentPerRequestResource.class);
+ classes.add(JCDIBeanDependentExceptionMapper.class);
+ classes.add(StutteringEchoResource.class);
+ classes.add(StutteringEcho.class);
+ classes.add(ReversingEchoResource.class);
+ classes.add(CounterResource.class);
+ classes.add(ConstructorInjectedResource.class);
+ classes.add(ProducerResource.class);
+ classes.add(FirstNonJaxRsBeanInjectedResource.class);
+ return classes;
+ }
+
+ // JERSEY-2531: make sure this type gets managed by CDI
+ @PostConstruct
+ public void postConstruct() {
+ LOGGER.info(String.format("%s: POST CONSTRUCT.", this.getClass().getName()));
+ postConstructCounter.incrementAndGet();
+ if (bm == null) {
+ throw new IllegalStateException("BeanManager should have been injected into a CDI managed bean.");
+ }
+ if (postConstructCounter.intValue() > 1) {
+ throw new IllegalStateException("postConstruct should have been invoked only once on app scoped bean.");
+ }
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOGGER.info(String.format("%s: PRE DESTROY.", this.getClass().getName()));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MethodProducedBean.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MethodProducedBean.java
new file mode 100644
index 0000000..94f842f
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MethodProducedBean.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.inject.Vetoed;
+
+/**
+ * A bean that would be produced by a CDI producer method.
+ * This is to make sure we do not mess up with CDI producers with HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Vetoed
+public class MethodProducedBean<T> implements ValueHolder<T> {
+
+ private final T value;
+
+ /**
+ * Make an instance with given value.
+ *
+ * @param value
+ */
+ public MethodProducedBean(T value) {
+ this.value = value;
+ }
+
+ /**
+ * Value getter.
+ *
+ * @return value.
+ */
+ @Override
+ public T getValue() {
+ return value;
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ProducerResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ProducerResource.java
new file mode 100644
index 0000000..4588692
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ProducerResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * This one will get injected with a CDI producer.
+ * HK2 should not mess up with this.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("producer")
+public class ProducerResource {
+
+ @Inject
+ MethodProducedBean<String> m;
+
+ @Inject
+ FieldProducedBean<String> f;
+
+ /**
+ * Return field produced bean value.
+ *
+ * @return value from field produced bean.
+ */
+ @Path("f")
+ @GET
+ public String getFieldValue() {
+ return f.getValue();
+ }
+
+ /**
+ * Return method produced bean value.
+ *
+ * @return value from method produced bean.
+ */
+ @Path("m")
+ @GET
+ public String getMethodValue() {
+ return m.getValue();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReverseEcho.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReverseEcho.java
new file mode 100644
index 0000000..b385655
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReverseEcho.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Echo implementation to reverse given input.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Reversing
+public class ReverseEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return reverseString(s);
+ }
+
+ private String reverseString(final String s) {
+ final int len = s.length();
+
+ char[] chars = new char[len];
+ for (int i = 0; i < len; i++) {
+ chars[i] = s.charAt(len - i - 1);
+ }
+ return new String(chars);
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Reversing.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Reversing.java
new file mode 100644
index 0000000..afe0ff5
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Reversing.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for reversing echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface Reversing {
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReversingEchoResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReversingEchoResource.java
new file mode 100644
index 0000000..c1eef59
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ReversingEchoResource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+/**
+ * CDI backed JAX-RS resource to reverse input query parameter using
+ * qualified injection to get a CDI backed service provider.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("reverse")
+public class ReversingEchoResource {
+
+ @Inject @Reversing EchoService echoService;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondNonJaxRsBeanInjectedResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondNonJaxRsBeanInjectedResource.java
new file mode 100644
index 0000000..eb4650a
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondNonJaxRsBeanInjectedResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * JAX-RS resource that gets injected with a CDI managed bean,
+ * that includes JAX-RS injection points. The very same bean
+ * gets injected also to {@link FirstNonJaxRsBeanInjectedResource}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("non-jaxrs-bean-injected")
+@RequestScoped
+public class SecondNonJaxRsBeanInjectedResource {
+
+ @Inject
+ JaxRsInjectedBean bean;
+
+ @GET
+ @Path("path/2")
+ public String getPath() {
+ return bean.getUriInfo().getPath();
+ }
+
+ @GET
+ @Path("header/2")
+ public String getAcceptHeader() {
+ return bean.getTestHeader();
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondaryApplication.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondaryApplication.java
new file mode 100644
index 0000000..fccc031
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/SecondaryApplication.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Secondary JAX-RS application to configure resources.
+ * This one is to make sure two Jersey apps could co-exist
+ * in CDI managed environment and JAX-RS injection keeps
+ * functioning as expected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("secondary")
+@ApplicationScoped
+public class SecondaryApplication extends Application {
+
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(SecondNonJaxRsBeanInjectedResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Stuttering.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Stuttering.java
new file mode 100644
index 0000000..a1cc1a8
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Stuttering.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for stuttering echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface Stuttering {
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEcho.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEcho.java
new file mode 100644
index 0000000..0579f8c
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEcho.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Echo implementation to stutter given input n-times.
+ * The stutter factor could be set via JAX-RS interface.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stuttering
+@ApplicationScoped
+@Path("stutter-service-factor")
+public class StutteringEcho implements EchoService {
+
+ private static final int MIN_FACTOR = 2;
+ private int factor = MIN_FACTOR;
+
+ @Override
+ public String echo(String s) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < factor; i++) {
+ result.append(s);
+ }
+ return result.toString();
+ }
+
+ @PUT
+ public void setFactor(String factor) {
+ this.factor = ensureValidInput(factor);
+ }
+
+ @GET
+ public String getFactor() {
+ return Integer.toString(factor);
+ }
+
+ private int ensureValidInput(String factor) throws WebApplicationException {
+ try {
+ final int newValue = Integer.parseInt(factor);
+ if (newValue < MIN_FACTOR) {
+ throw createWebAppException(String.format("New factor can not be lesser then %d!", MIN_FACTOR));
+ }
+ return newValue;
+ } catch (NumberFormatException nfe) {
+ throw createWebAppException(String.format("Error parsing %s as an integer!", factor));
+ }
+ }
+
+ private WebApplicationException createWebAppException(String message) {
+
+ return new WebApplicationException(
+
+ Response.status(Response.Status.BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity(Entity.text(message)).build());
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEchoResource.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEchoResource.java
new file mode 100644
index 0000000..c3d5a56
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/StutteringEchoResource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * CDI backed JAX-RS resource to stutter input query parameter.
+ * Uses qualified injection to get a CDI backed service provider.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("stutter")
+public class StutteringEchoResource {
+
+ @Inject @Stuttering EchoService echoService;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ValueHolder.java b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ValueHolder.java
new file mode 100644
index 0000000..11046fc
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/ValueHolder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Helper type to check CDI producer mechanism is not broken
+ * by automatic HK2/CDI bindings.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface ValueHolder<T> {
+
+ /**
+ * Value getter.
+ *
+ * @return value.
+ */
+ T getValue();
+}
diff --git a/tests/integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-test-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/tests/integration/cdi-test-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..7331615
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.resources.CustomExtension
diff --git a/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ff67ca5
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <env-entry>
+ <env-entry-name>injectedResource</env-entry-name>
+ <env-entry-type>java.lang.Integer</env-entry-type>
+ <env-entry-value>10</env-entry-value>
+ </env-entry>
+</web-app>
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
new file mode 100644
index 0000000..a3137a9
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.jboss.weld.environment.se.Weld;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-test-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiTest extends JerseyTest {
+
+ Weld weld;
+
+ @Override
+ public void setUp() throws Exception {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ weld.shutdown();
+ super.tearDown();
+ }
+
+ @Override
+ protected Application configure() {
+ return new MainApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-test-webapp/main").build();
+ }
+}
+
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectionTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectionTest.java
new file mode 100644
index 0000000..0263084
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ConstructorInjectionTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import org.junit.Test;
+
+/**
+ * Part of JERSEY-2526 reproducer. Without the fix, the application would
+ * not deploy at all. This is just to make sure the JAX-RS parameter producer
+ * keeps working as expected without regressions.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oralc.com)
+ */
+public class ConstructorInjectionTest extends CdiTest {
+
+ @Test
+ public void testConstructorInjectedResource() {
+
+ final WebTarget target = target().path("ctor-injected");
+
+ final Response pathParamResponse = target.path("pathParam").request().get();
+ assertThat(pathParamResponse.getStatus(), is(200));
+ assertThat(pathParamResponse.readEntity(String.class), is("pathParam"));
+
+ final Response queryParamResponse = target.path("queryParam").queryParam("q", "123").request().get();
+ assertThat(queryParamResponse.getStatus(), is(200));
+ assertThat(queryParamResponse.readEntity(String.class), is("123"));
+
+ final Response matrixParamResponse = target.path("matrixParam").matrixParam("m", "456").request().get();
+ assertThat(matrixParamResponse.getStatus(), is(200));
+ assertThat(matrixParamResponse.readEntity(String.class), is("456"));
+
+ final Response headerParamResponse = target.path("headerParam").request().header("Custom-Header", "789").get();
+ assertThat(headerParamResponse.getStatus(), is(200));
+ assertThat(headerParamResponse.readEntity(String.class), is("789"));
+
+ final Response cdiParamResponse = target.path("cdiParam").request().get();
+ assertThat(cdiParamResponse.getStatus(), is(200));
+ assertThat(cdiParamResponse.readEntity(String.class), is("cdi-produced"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CounterTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CounterTest.java
new file mode 100644
index 0000000..62f4f5d
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CounterTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * Part of JERSEY-2641 reproducer. Accessing CDI bean that has custom CDI
+ * extension injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CounterTest extends CdiTest {
+
+ @Test
+ public void testGet() {
+
+ final WebTarget target = target().path("counter");
+
+ final Response firstResponse = target.request().get();
+ assertThat(firstResponse.getStatus(), is(200));
+ int firstNumber = Integer.decode(firstResponse.readEntity(String.class));
+
+ final Response secondResponse = target.request().get();
+ assertThat(secondResponse.getStatus(), is(200));
+ int secondNumber = Integer.decode(secondResponse.readEntity(String.class));
+
+ assertTrue("Second request should have greater number!", secondNumber > firstNumber);
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedCdiBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedCdiBeanTest.java
new file mode 100644
index 0000000..56cc87b
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/JaxRsInjectedCdiBeanTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test that a raw CDI managed bean gets JAX-RS injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsInjectedCdiBeanTest extends CdiTest {
+
+ @Test
+ public void testPathAndHeader() {
+ _testPathAndHeader(target());
+ }
+
+ public static void _testPathAndHeader(final WebTarget webTarget) {
+ final WebTarget target = webTarget.path("non-jaxrs-bean-injected");
+
+ final Response pathResponse = target.path("path/1").request().get();
+ assertThat(pathResponse.getStatus(), is(200));
+ final String path = pathResponse.readEntity(String.class);
+
+ assertThat(path, is("non-jaxrs-bean-injected/path/1"));
+
+ final Response headerResponse = target.path("header/1").request().header("x-test", "bummer").get();
+ assertThat(headerResponse.getStatus(), is(200));
+ final String header = headerResponse.readEntity(String.class);
+
+ assertThat(header, is("bummer"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/NonJaxRsBeanJaxRsInjectionTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/NonJaxRsBeanJaxRsInjectionTest.java
new file mode 100644
index 0000000..2775ebf
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/NonJaxRsBeanJaxRsInjectionTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Properties;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainerProvider;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.glassfish.grizzly.http.server.HttpHandler;
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.hamcrest.CoreMatchers;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test two Jersey apps running simultaneously within a single Grizzly HTTP server
+ * to make sure two injection managers do not interfere. The test is not executed
+ * if other than the default (Grizzly) test container has been set.
+ * For Servlet based container testing, the other two tests, {@link JaxRsInjectedCdiBeanTest}
+ * and {@link SecondJaxRsInjectedCdiBeanTest},
+ * do the same job, because the WAR application contains both Jersey apps already.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class NonJaxRsBeanJaxRsInjectionTest {
+
+ public static final String MAIN_URI = "/main";
+ public static final String SECONDARY_URI = "/secondary";
+
+ public static final String PORT_NUMBER = getSystemProperty(TestProperties.CONTAINER_PORT,
+ Integer.toString(TestProperties.DEFAULT_CONTAINER_PORT));
+
+ private static final URI MAIN_APP_URI = URI.create("http://localhost:" + PORT_NUMBER + MAIN_URI);
+ private static final URI SECONDARY_APP_URI = URI.create("http://localhost:" + PORT_NUMBER + SECONDARY_URI);
+
+ private static final boolean isDefaultTestContainerFactorySet = isDefaultTestContainerFactorySet();
+
+ Weld weld;
+ HttpServer httpServer;
+
+ Client client;
+ WebTarget mainTarget, secondaryTarget;
+
+ @Before
+ public void before() throws IOException {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+
+ if (isDefaultTestContainerFactorySet) {
+ initializeWeld();
+ startGrizzlyContainer();
+ initializeClient();
+ }
+ }
+
+ @After
+ public void after() {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ if (isDefaultTestContainerFactorySet) {
+ httpServer.shutdownNow();
+ weld.shutdown();
+ client.close();
+ }
+ }
+ }
+
+ @Test
+ public void testPathAndHeader() throws Exception {
+ Assume.assumeThat(isDefaultTestContainerFactorySet, CoreMatchers.is(true));
+ JaxRsInjectedCdiBeanTest._testPathAndHeader(mainTarget);
+ SecondJaxRsInjectedCdiBeanTest._testPathAndHeader(secondaryTarget);
+ }
+
+ private void initializeWeld() {
+ weld = new Weld();
+ weld.initialize();
+ }
+
+ private void startGrizzlyContainer() throws IOException {
+ final ResourceConfig firstConfig = ResourceConfig.forApplicationClass(MainApplication.class);
+ final ResourceConfig secondConfig = ResourceConfig.forApplicationClass(SecondaryApplication.class);
+
+ httpServer = GrizzlyHttpServerFactory.createHttpServer(MAIN_APP_URI, firstConfig, false);
+ final HttpHandler secondHandler = createGrizzlyContainer(secondConfig);
+ httpServer.getServerConfiguration().addHttpHandler(secondHandler, SECONDARY_URI);
+ httpServer.start();
+ }
+
+ private GrizzlyHttpContainer createGrizzlyContainer(final ResourceConfig resourceConfig) {
+ return (new GrizzlyHttpContainerProvider()).createContainer(GrizzlyHttpContainer.class, resourceConfig);
+ }
+
+ private void initializeClient() {
+ client = ClientBuilder.newClient();
+ mainTarget = client.target(MAIN_APP_URI);
+ secondaryTarget = client.target(SECONDARY_APP_URI);
+ }
+
+ private static boolean isDefaultTestContainerFactorySet() {
+ final String testContainerFactory = getSystemProperty(TestProperties.CONTAINER_FACTORY, null);
+ return testContainerFactory == null || TestProperties.DEFAULT_CONTAINER_FACTORY.equals(testContainerFactory);
+ }
+
+ private static String getSystemProperty(final String propertyName, final String defaultValue) {
+ final Properties systemProperties = System.getProperties();
+ return systemProperties.getProperty(propertyName, defaultValue);
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestBeanTest.java
new file mode 100644
index 0000000..19d3984
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestBeanTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the request scoped resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class PerRequestBeanTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"alpha"},
+ {"AAA"},
+ {"$%^"},
+ {"a b"}
+ });
+ }
+
+ final String x;
+
+ /**
+ * Create x new test case based on the above defined parameters.
+ *
+ * @param x query parameter value
+ */
+ public PerRequestBeanTest(String x) {
+ this.x = x;
+ }
+
+ @Test
+ public void testGet() {
+
+ final WebTarget target = target().path("jcdibean/per-request").queryParam("x", x);
+
+ String s = target.request().get(String.class);
+
+ assertThat(s, containsString(target.getUri().toString()));
+ assertThat(s, containsString(String.format("queryParam=%s", x)));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestDependentBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestDependentBeanTest.java
new file mode 100644
index 0000000..dd2e879
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/PerRequestDependentBeanTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the request scoped managed bean resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class PerRequestDependentBeanTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"alpha"},
+ {"AAA"},
+ {"$%^"},
+ {"a b"}
+ });
+ }
+
+ final String x;
+
+ /**
+ * Create x new test case based on the above defined parameters.
+ *
+ * @param x query parameter value
+ */
+ public PerRequestDependentBeanTest(String x) {
+ this.x = x;
+ }
+
+ @Test
+ public void testGet() {
+
+ final WebTarget target = target().path("jcdibean/dependent/per-request").queryParam("x", x);
+
+ String s = target.request().get(String.class);
+
+ assertThat(s, containsString(target.getUri().toString()));
+ assertThat(s, containsString(String.format("queryParam=%s", x)));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ProducerTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ProducerTest.java
new file mode 100644
index 0000000..1ecf8cd
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ProducerTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * Check that automatic HK2 bindings do not break CDI producer mechanism.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ProducerTest extends CdiTest {
+
+ @Test
+ public void testGet() {
+
+ final WebTarget target = target().path("producer");
+
+ final Response fieldResponse = target.path("f").request().get();
+ assertThat(fieldResponse.getStatus(), is(200));
+ assertThat(fieldResponse.readEntity(String.class), is("field"));
+
+ final Response methodResponse = target.path("m").request().get();
+ assertThat(methodResponse.getStatus(), is(200));
+ assertThat(methodResponse.readEntity(String.class), is("method"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/QualifiedInjectionSetGetTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/QualifiedInjectionSetGetTest.java
new file mode 100644
index 0000000..9a01764
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/QualifiedInjectionSetGetTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Qualifier;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * Test CDI bean injected using a {@link Qualifier}
+ * is setup via JAX-RS interface first.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class QualifiedInjectionSetGetTest extends CdiTest {
+
+ @Test
+ public void testSetGet() {
+
+ final WebTarget factorTarget = target().path("stutter-service-factor");
+ final WebTarget stutterTarget = target().path("stutter");
+
+ factorTarget.request().put(Entity.text("3"));
+ final String shouldBeTrippled = stutterTarget.queryParam("s", "lincoln").request().get(String.class);
+
+ assertThat(shouldBeTrippled, is("lincolnlincolnlincoln"));
+
+ factorTarget.request().put(Entity.text("2"));
+ final String shouldBeDoubled = stutterTarget.queryParam("s", "lincoln").request().get(String.class);
+
+ assertThat(shouldBeDoubled, is("lincolnlincoln"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ReverseEchoTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ReverseEchoTest.java
new file mode 100644
index 0000000..0c3c5ca
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ReverseEchoTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for qualified injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ReverseEchoTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"alpha", "ahpla"},
+ {"gogol", "logog"},
+ {"elcaro", "oracle"}
+ });
+ }
+
+ final String in, out;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param in query parameter.
+ * @param out expected output.
+ */
+ public ReverseEchoTest(String in, String out) {
+ this.in = in;
+ this.out = out;
+ }
+
+ @Test
+ public void testGet() {
+ WebTarget reverseService = target().path("reverse").queryParam("s", in);
+ String s = reverseService.request().get(String.class);
+ assertThat(s, equalTo(out));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SecondJaxRsInjectedCdiBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SecondJaxRsInjectedCdiBeanTest.java
new file mode 100644
index 0000000..a273de4
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SecondJaxRsInjectedCdiBeanTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test that a raw CDI managed bean gets JAX-RS injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class SecondJaxRsInjectedCdiBeanTest extends JerseyTest {
+ Weld weld;
+
+ @Override
+ public void setUp() throws Exception {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ weld.shutdown();
+ super.tearDown();
+ }
+
+ @Override
+ protected Application configure() {
+ return new SecondaryApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-test-webapp/secondary").build();
+ }
+
+ @Test
+ public void testPathAndHeader() {
+ _testPathAndHeader(target());
+ }
+
+ public static void _testPathAndHeader(final WebTarget webTarget) {
+ final WebTarget target = webTarget.path("non-jaxrs-bean-injected");
+
+ final Response pathResponse = target.path("path/2").request().get();
+ assertThat(pathResponse.getStatus(), is(200));
+ final String path = pathResponse.readEntity(String.class);
+
+ assertThat(path, is("non-jaxrs-bean-injected/path/2"));
+
+ final Response headerResponse = target.path("header/2").request().header("x-test", "bummer2").get();
+ assertThat(headerResponse.getStatus(), is(200));
+ final String header = headerResponse.readEntity(String.class);
+
+ assertThat(header, is("bummer2"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonBeanTest.java
new file mode 100644
index 0000000..0b35e30
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonBeanTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the application scoped resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class SingletonBeanTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"alpha", "beta"},
+ {"1", "2"}
+ });
+ }
+
+ final String p, x;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param p path parameter.
+ * @param x query parameter.
+ */
+ public SingletonBeanTest(String p, String x) {
+ this.p = p;
+ this.x = x;
+ }
+
+ @Test
+ public void testGet() {
+ final WebTarget singleton = target().path("jcdibean/singleton").path(p).queryParam("x", x);
+ String s = singleton.request().get(String.class);
+ assertThat(s, containsString(singleton.getUri().toString()));
+ assertThat(s, containsString(String.format("p=%s", p)));
+ assertThat(s, containsString(String.format("queryParam=%s", x)));
+ }
+
+ @Test
+ public void testCounter() {
+
+ final WebTarget counter = target().path("jcdibean/singleton").path(p).queryParam("x", x).path("counter");
+
+ if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) {
+ // TODO: remove this workaround once JERSEY-2744 is resolved
+ counter.request().put(Entity.text("10"));
+ }
+
+ String c10 = counter.request().get(String.class);
+ assertThat(c10, containsString("10"));
+
+ String c11 = counter.request().get(String.class);
+ assertThat(c11, containsString("11"));
+
+ counter.request().put(Entity.text("32"));
+
+ String c32 = counter.request().get(String.class);
+ assertThat(c32, containsString("32"));
+
+ counter.request().put(Entity.text("10"));
+ }
+
+ @Test
+ public void testException() {
+ final WebTarget exception = target().path("jcdibean/singleton").path(p).queryParam("x", x).path("exception");
+ assertThat(exception.request().get().readEntity(String.class), containsString("JDCIBeanException"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonDependentBeanTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonDependentBeanTest.java
new file mode 100644
index 0000000..5a21ae8
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/SingletonDependentBeanTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the application scoped managed bean resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class SingletonDependentBeanTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"alpha", "beta"},
+ {"1", "2"}
+ });
+ }
+
+ final String p, x;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param p path parameter.
+ * @param x query parameter.
+ */
+ public SingletonDependentBeanTest(String p, String x) {
+ this.p = p;
+ this.x = x;
+ }
+
+ @Test
+ public void testGet() {
+ final WebTarget singleton = target().path("jcdibean/dependent/singleton").path(p).queryParam("x", x);
+ String s = singleton.request().get(String.class);
+ assertThat(s, containsString(singleton.getUri().toString()));
+ assertThat(s, containsString(String.format("p=%s", p)));
+ assertThat(s, containsString(String.format("queryParam=%s", x)));
+ }
+
+ @Test
+ public void testCounter() {
+
+ final WebTarget counter = target().path("jcdibean/dependent/singleton").path(p).queryParam("x", x).path("counter");
+
+ if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) {
+ // TODO: remove this workaround once JERSEY-2744 is resolved
+ counter.request().put(Entity.text("10"));
+ }
+
+ String c10 = counter.request().get(String.class);
+ assertThat(c10, containsString("10"));
+
+ String c11 = counter.request().get(String.class);
+ assertThat(c11, containsString("11"));
+
+ counter.request().put(Entity.text("32"));
+
+ String c32 = counter.request().get(String.class);
+ assertThat(c32, containsString("32"));
+
+ counter.request().put(Entity.text("10"));
+ }
+
+ @Test
+ public void testException() {
+ final WebTarget exception = target().path("jcdibean/dependent/singleton").path(p).queryParam("x", x).path("exception");
+ assertThat(exception.request().get().readEntity(String.class), containsString("JDCIBeanDependentException"));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/StutterEchoTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/StutterEchoTest.java
new file mode 100644
index 0000000..bc0dc27
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/StutterEchoTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for qualified injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class StutterEchoTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][]{
+ {"alpha", "alphaalpha"},
+ {"gogol", "gogolgogol"},
+ {"elcaro", "elcaroelcaro"}
+ });
+ };
+
+ final String in, out;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param in query parameter.
+ * @param out expected output.
+ */
+ public StutterEchoTest(String in, String out) {
+ this.in = in;
+ this.out = out;
+ }
+
+ @Test
+ public void testGet() {
+ String s = target().path("stutter").queryParam("s", in).request().get(String.class);
+ assertThat(s, equalTo(out));
+ }
+}
diff --git a/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TimerTest.java b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TimerTest.java
new file mode 100644
index 0000000..ba4ba33
--- /dev/null
+++ b/tests/integration/cdi-test-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/TimerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * Reproducer for JERSEY-1747.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class TimerTest extends CdiTest {
+
+ @Test
+ public void testGet() {
+
+ final WebTarget target = target().path("jcdibean/dependent/timer");
+
+ final Response firstResponse = target.request().get();
+ assertThat(firstResponse.getStatus(), is(200));
+ long firstMillis = Long.decode(firstResponse.readEntity(String.class));
+ sleep(2);
+
+ final Response secondResponse = target.request().get();
+ assertThat(secondResponse.getStatus(), is(200));
+ long secondMillis = Long.decode(secondResponse.readEntity(String.class));
+
+ assertTrue("Second request should have greater millis!", secondMillis > firstMillis);
+ }
+
+ private void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(TimerTest.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
new file mode 100644
index 0000000..a491ec4
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-with-jersey-injection-custom-cfg-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-with-jersey-injection-custom-cfg-webapp</name>
+
+ <description>
+ Jersey CDI test web application, this one uses Jersey (non JAX-RS) component injection and Jersey/CDI SPI to config
+ HK2 custom bindings.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x-transaction</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
new file mode 100644
index 0000000..16f3efb
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.ApplicationScoped;
+
+
+/**
+ * Application specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@AppSpecific
+@ApplicationScoped
+public class AppEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "App: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
new file mode 100644
index 0000000..f153c02
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-ctor-injected")
+public class AppScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ Provider<ContainerRequest> request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+ // Jersey/HK2 custom injected
+ @Inject
+ Hk2InjectedType hk2Injected;
+
+ // to make weld happy
+ public AppScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public AppScopedCtorInjectedResource(@AppSpecific final EchoService echoService,
+ final Provider<ContainerRequest> request,
+ final ExceptionMappers mappers,
+ final Provider<MonitoringStatistics> stats,
+ final MyApplication.MyInjection customInjected,
+ final Hk2InjectedType hk2Injected) {
+ this.echoService = echoService;
+ this.request = request;
+ this.mappers = mappers;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ this.hk2Injected = hk2Injected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") final String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
new file mode 100644
index 0000000..8999f6a
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+import org.glassfish.jersey.tests.cdi.resources.MyApplication.MyInjection;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-field-injected")
+public class AppScopedFieldInjectedResource {
+
+ // CDI injected
+ @Inject
+ @AppSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ Provider<ContainerRequest> request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injection
+ @Inject
+ MyInjection customInjected;
+ // Jersey/HK2 custom injection
+ @Inject
+ Hk2InjectedType hk2Injected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
new file mode 100644
index 0000000..000fc6d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for application specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface AppSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
new file mode 100644
index 0000000..8745b22
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Qualifier;
+
+/**
+ * Simple echo service to test injections using {@link Qualifier}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface EchoService {
+
+ /**
+ * Provide an echoed response.
+ *
+ * @param s String to be echoed.
+ * @return echoed input.
+ */
+ public String echo(String s);
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Hk2InjectedType.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Hk2InjectedType.java
new file mode 100644
index 0000000..d7d73ed
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/Hk2InjectedType.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * CDI compliant bean. Injection will be delegated to HK2 anyway.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Hk2InjectedType {
+
+ private final String name;
+
+ /**
+ * No-arg constructor makes this bean suitable for CDI injection.
+ */
+ public Hk2InjectedType() {
+ name = "CDI would love this";
+ }
+
+ /**
+ * Hk2 custom binder is going to use this one.
+ *
+ * @param name
+ */
+ public Hk2InjectedType(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Simple getter to prove where this bean was initialized.
+ *
+ * @return name as defined at bean initialization.
+ */
+ public String getName() {
+ return name;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..a5fc240
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.monitoring.MonitoringFeature;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends ResourceConfig {
+
+ public static class MyInjection {
+
+ private final String name;
+
+ public MyInjection(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public MyApplication() {
+
+ // JAX-RS resource classes
+ register(AppScopedFieldInjectedResource.class);
+ register(AppScopedCtorInjectedResource.class);
+ register(RequestScopedFieldInjectedResource.class);
+ register(RequestScopedCtorInjectedResource.class);
+
+ register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjection("1st: no way CDI would chime in")).to(MyInjection.class);
+ bind(new Hk2InjectedType("2nd: no way CDI would chime in")).to(Hk2InjectedType.class);
+ }
+ });
+
+ // Jersey monitoring
+ register(MonitoringFeature.class);
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java
new file mode 100644
index 0000000..365e41b
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider;
+
+/**
+ * Tell Jersey CDI extension what types should be bridged from HK2 to CDI.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class MyHk2TypesProvider implements Hk2CustomBoundTypesProvider {
+
+ @Override
+ public Set<Type> getHk2Types() {
+ return new HashSet<Type>() {{
+ add(Hk2InjectedType.class);
+ add(MyApplication.MyInjection.class);
+ }};
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
new file mode 100644
index 0000000..e0c26bc
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Request specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestSpecific
+public class RequestEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "Request: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
new file mode 100644
index 0000000..881895d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-ctor-injected")
+public class RequestScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ ContainerRequest request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+ // Jersey/HK2 custom injected
+ Hk2InjectedType hk2Injected;
+
+ // to make weld happy
+ public RequestScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public RequestScopedCtorInjectedResource(@RequestSpecific final EchoService echoService,
+ final ContainerRequest request,
+ final ExceptionMappers mappers,
+ final Provider<MonitoringStatistics> stats,
+ final MyApplication.MyInjection customInjected,
+ final Hk2InjectedType hk2Injected) {
+
+ this.echoService = echoService;
+ this.mappers = mappers;
+ this.request = request;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ this.hk2Injected = hk2Injected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") final String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
new file mode 100644
index 0000000..a24f88f
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-field-injected")
+public class RequestScopedFieldInjectedResource {
+
+ // built-in CDI bean
+ @Inject
+ BeanManager beanManager;
+
+ // CDI injected
+ @Inject
+ @RequestSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ ContainerRequest request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Custom Jersey/HK2 injected
+ @Inject
+ MyApplication.MyInjection customInjected;
+ // Custom Jersey/HK2 injected
+ @Inject
+ Hk2InjectedType hk2Injected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+
+ @GET
+ @Path("bm")
+ public String getBm() {
+ return beanManager.toString();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
new file mode 100644
index 0000000..05f048d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for request specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface RequestSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider
new file mode 100644
index 0000000..8ad35f8
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.resources.MyHk2TypesProvider
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ff67ca5
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <env-entry>
+ <env-entry-name>injectedResource</env-entry-name>
+ <env-entry-type>java.lang.Integer</env-entry-type>
+ <env-entry-value>10</env-entry-value>
+ </env-entry>
+</web-app>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
new file mode 100644
index 0000000..bafe964
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-with-jersey-injection-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-with-jersey-injection-custom-cfg-webapp").build();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
new file mode 100644
index 0000000..0b58f6d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test custom HK2 injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class CustomInjectionTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"},
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public CustomInjectionTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side,
+ * and the custom bound instance of {@link Hk2InjectedType} gets injected.
+ */
+ @Test
+ public void testCustomHk2Injection1() {
+ final WebTarget target = target().path(resource).path("custom");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("1st: no way CDI would chime in"));
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side,
+ * and the custom bound instance of {@link MyApplication.MyInjection} gets injected.
+ */
+ @Test
+ public void testCustomHk2Injection2() {
+ final WebTarget target = target().path(resource).path("custom2");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("2nd: no way CDI would chime in"));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
new file mode 100644
index 0000000..5675349
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for exception mapper injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ExceptionMappersTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"},
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public ExceptionMappersTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side, and for two
+ * the injected mappers remains the same across requests.
+ */
+ @Test
+ public void testMappersNotNull() {
+ final WebTarget target = target().path(resource).path("mappers");
+ final Response firstResponse = target.request().get();
+ assertThat(firstResponse.getStatus(), equalTo(200));
+ final String firstValue = firstResponse.readEntity(String.class);
+ assertThat(target.request().get(String.class), equalTo(firstValue));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
new file mode 100644
index 0000000..25aed86
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for monitoring statistics injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class MonitoringTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of resource to be tested.
+ */
+ public MonitoringTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Make several requests and check the counter keeps incrementing.
+ *
+ * @throws Exception in case of unexpected test failure.
+ */
+ @Test
+ public void testRequestCount() throws Exception {
+ final WebTarget target = target().path(resource).path("requestCount");
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ final int start = Integer.decode(target.request().get(String.class));
+ for (int i = 1; i < 4; i++) {
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ final int next = Integer.decode(target.request().get(String.class));
+ assertThat(String.format("testing %s", resource), next, equalTo(start + i));
+ }
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
new file mode 100644
index 0000000..a31befa
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-cfg-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test injection of request depending instances works as expected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class RequestSensitiveTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected", "alpha", "App: alpha"},
+ {"app-field-injected", "gogol", "App: gogol"},
+ {"app-field-injected", "elcaro", "App: elcaro"},
+ {"app-ctor-injected", "alpha", "App: alpha"},
+ {"app-ctor-injected", "gogol", "App: gogol"},
+ {"app-ctor-injected", "elcaro", "App: elcaro"},
+ {"request-field-injected", "alpha", "Request: alpha"},
+ {"request-field-injected", "gogol", "Request: gogol"},
+ {"request-field-injected", "oracle", "Request: oracle"},
+ {"request-ctor-injected", "alpha", "Request: alpha"},
+ {"request-ctor-injected", "gogol", "Request: gogol"},
+ {"request-ctor-injected", "oracle", "Request: oracle"}
+ });
+ }
+
+ final String resource, straight, echoed;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of the resource to be tested.
+ * @param straight request specific input.
+ * @param echoed CDI injected service should produce this out of previous, straight, parameter.
+ */
+ public RequestSensitiveTest(final String resource, final String straight, final String echoed) {
+ this.resource = resource;
+ this.straight = straight;
+ this.echoed = echoed;
+ }
+
+ @Test
+ public void testCdiInjection() {
+ final String s = target().path(resource).queryParam("s", straight).request().get(String.class);
+ assertThat(s, equalTo(echoed));
+ }
+
+ @Test
+ public void testHk2Injection() {
+ final String s = target().path(resource).path("path").path(straight).request().get(String.class);
+ assertThat(s, equalTo(String.format("%s/path/%s", resource, straight)));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
new file mode 100644
index 0000000..5980238
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-with-jersey-injection-custom-hk2-banned-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-with-jersey-injection-custom-hk2-banned-webapp</name>
+
+ <description>
+ Jersey CDI test web application, this one uses Jersey (non JAX-RS) component injection HK2 custom binding has been banned.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x-transaction</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
new file mode 100644
index 0000000..16f3efb
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.ApplicationScoped;
+
+
+/**
+ * Application specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@AppSpecific
+@ApplicationScoped
+public class AppEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "App: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
new file mode 100644
index 0000000..a50a688
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-ctor-injected")
+public class AppScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ Provider<ContainerRequest> request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+ // Jersey/HK2 custom injected
+ @Inject
+ CdiInjectedType hk2Injected;
+
+ // to make weld happy
+ public AppScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public AppScopedCtorInjectedResource(@AppSpecific final EchoService echoService,
+ final Provider<ContainerRequest> request,
+ final ExceptionMappers mappers,
+ final Provider<MonitoringStatistics> stats,
+ final MyApplication.MyInjection customInjected,
+ final CdiInjectedType hk2Injected) {
+ this.echoService = echoService;
+ this.request = request;
+ this.mappers = mappers;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ this.hk2Injected = hk2Injected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") final String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
new file mode 100644
index 0000000..8c16474
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+import org.glassfish.jersey.tests.cdi.resources.MyApplication.MyInjection;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-field-injected")
+public class AppScopedFieldInjectedResource {
+
+ // CDI injected
+ @Inject
+ @AppSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ Provider<ContainerRequest> request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injection
+ @Inject
+ MyInjection customInjected;
+ // Jersey/HK2 custom injection
+ @Inject
+ CdiInjectedType hk2Injected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
new file mode 100644
index 0000000..000fc6d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for application specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface AppSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiInjectedType.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiInjectedType.java
new file mode 100644
index 0000000..84b1fc2
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/CdiInjectedType.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * CDI compliant bean. Injection will be done by CDI in this application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiInjectedType {
+
+ private final String name;
+
+ /**
+ * No-arg constructor makes this bean suitable for CDI injection.
+ */
+ public CdiInjectedType() {
+ name = "CDI would love this";
+ }
+
+ /**
+ * Hk2 custom binder is going to use this one.
+ *
+ * @param name
+ */
+ public CdiInjectedType(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Simple getter to prove where this bean was initialized.
+ *
+ * @return name as defined at bean initialization.
+ */
+ public String getName() {
+ return name;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
new file mode 100644
index 0000000..8745b22
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Qualifier;
+
+/**
+ * Simple echo service to test injections using {@link Qualifier}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface EchoService {
+
+ /**
+ * Provide an echoed response.
+ *
+ * @param s String to be echoed.
+ * @return echoed input.
+ */
+ public String echo(String s);
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..829f43a
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.monitoring.MonitoringFeature;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends ResourceConfig {
+
+ public static class MyInjection {
+
+ private final String name;
+
+ public MyInjection() {
+ name = "CDI injected";
+ }
+
+ public MyInjection(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public MyApplication() {
+
+ // JAX-RS resource classes
+ register(AppScopedFieldInjectedResource.class);
+ register(AppScopedCtorInjectedResource.class);
+ register(RequestScopedFieldInjectedResource.class);
+ register(RequestScopedCtorInjectedResource.class);
+
+ register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjection("1st: unused HK2 binding")).to(MyInjection.class);
+ bind(new CdiInjectedType("2nd: unused HK2 binding")).to(CdiInjectedType.class);
+ }
+ });
+
+ // Jersey monitoring
+ register(MonitoringFeature.class);
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
new file mode 100644
index 0000000..e0c26bc
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Request specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestSpecific
+public class RequestEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "Request: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
new file mode 100644
index 0000000..0080e0d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-ctor-injected")
+public class RequestScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ ContainerRequest request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+ // Jersey/HK2 custom injected
+ CdiInjectedType hk2Injected;
+
+ // to make weld happy
+ public RequestScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public RequestScopedCtorInjectedResource(@RequestSpecific final EchoService echoService,
+ final ContainerRequest request,
+ final ExceptionMappers mappers,
+ final Provider<MonitoringStatistics> stats,
+ final MyApplication.MyInjection customInjected,
+ final CdiInjectedType hk2Injected) {
+
+ this.echoService = echoService;
+ this.mappers = mappers;
+ this.request = request;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ this.hk2Injected = hk2Injected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") final String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
new file mode 100644
index 0000000..eecf01e
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-field-injected")
+public class RequestScopedFieldInjectedResource {
+
+ // built-in CDI bean
+ @Inject
+ BeanManager beanManager;
+
+ // CDI injected
+ @Inject
+ @RequestSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ ContainerRequest request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Custom Jersey/HK2 injected
+ @Inject
+ MyApplication.MyInjection customInjected;
+ // Custom Jersey/HK2 injected
+ @Inject
+ CdiInjectedType hk2Injected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("custom2")
+ public String getCustom2() {
+ return hk2Injected.getName();
+ }
+
+ @GET
+ @Path("bm")
+ public String getBm() {
+ return beanManager.toString();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
new file mode 100644
index 0000000..05f048d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for request specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface RequestSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ff67ca5
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <env-entry>
+ <env-entry-name>injectedResource</env-entry-name>
+ <env-entry-type>java.lang.Integer</env-entry-type>
+ <env-entry-value>10</env-entry-value>
+ </env-entry>
+</web-app>
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
new file mode 100644
index 0000000..89cf238
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-with-jersey-injection-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-with-jersey-injection-custom-hk2-banned-webapp").build();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
new file mode 100644
index 0000000..6498726
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test custom HK2 injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class CustomInjectionTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"},
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public CustomInjectionTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side,
+ * and the custom bound instance of {@link CdiInjectedType} gets CDI injected.
+ */
+ @Test
+ public void testCustomHk2Injection1() {
+ final WebTarget target = target().path(resource).path("custom");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("CDI injected"));
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side,
+ * and the custom bound instance of {@link MyApplication.MyInjection} gets CDI injected.
+ */
+ @Test
+ public void testCustomHk2Injection2() {
+ final WebTarget target = target().path(resource).path("custom2");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("CDI would love this"));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
new file mode 100644
index 0000000..e87369f
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for exception mapper injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ExceptionMappersTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public ExceptionMappersTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side, and for two
+ * the injected mappers remains the same across requests.
+ */
+ @Test
+ public void testMappersNotNull() {
+ final WebTarget target = target().path(resource).path("mappers");
+ final Response firstResponse = target.request().get();
+ assertThat(firstResponse.getStatus(), equalTo(200));
+ final String firstValue = firstResponse.readEntity(String.class);
+ assertThat(target.request().get(String.class), equalTo(firstValue));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
new file mode 100644
index 0000000..25aed86
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for monitoring statistics injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class MonitoringTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of resource to be tested.
+ */
+ public MonitoringTest(final String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Make several requests and check the counter keeps incrementing.
+ *
+ * @throws Exception in case of unexpected test failure.
+ */
+ @Test
+ public void testRequestCount() throws Exception {
+ final WebTarget target = target().path(resource).path("requestCount");
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ final int start = Integer.decode(target.request().get(String.class));
+ for (int i = 1; i < 4; i++) {
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ final int next = Integer.decode(target.request().get(String.class));
+ assertThat(String.format("testing %s", resource), next, equalTo(start + i));
+ }
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
new file mode 100644
index 0000000..a31befa
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test injection of request depending instances works as expected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class RequestSensitiveTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected", "alpha", "App: alpha"},
+ {"app-field-injected", "gogol", "App: gogol"},
+ {"app-field-injected", "elcaro", "App: elcaro"},
+ {"app-ctor-injected", "alpha", "App: alpha"},
+ {"app-ctor-injected", "gogol", "App: gogol"},
+ {"app-ctor-injected", "elcaro", "App: elcaro"},
+ {"request-field-injected", "alpha", "Request: alpha"},
+ {"request-field-injected", "gogol", "Request: gogol"},
+ {"request-field-injected", "oracle", "Request: oracle"},
+ {"request-ctor-injected", "alpha", "Request: alpha"},
+ {"request-ctor-injected", "gogol", "Request: gogol"},
+ {"request-ctor-injected", "oracle", "Request: oracle"}
+ });
+ }
+
+ final String resource, straight, echoed;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of the resource to be tested.
+ * @param straight request specific input.
+ * @param echoed CDI injected service should produce this out of previous, straight, parameter.
+ */
+ public RequestSensitiveTest(final String resource, final String straight, final String echoed) {
+ this.resource = resource;
+ this.straight = straight;
+ this.echoed = echoed;
+ }
+
+ @Test
+ public void testCdiInjection() {
+ final String s = target().path(resource).queryParam("s", straight).request().get(String.class);
+ assertThat(s, equalTo(echoed));
+ }
+
+ @Test
+ public void testHk2Injection() {
+ final String s = target().path(resource).path("path").path(straight).request().get(String.class);
+ assertThat(s, equalTo(String.format("%s/path/%s", resource, straight)));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/pom.xml b/tests/integration/cdi-with-jersey-injection-webapp/pom.xml
new file mode 100644
index 0000000..d0e0c42
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>cdi-with-jersey-injection-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-cdi-with-jersey-injection-webapp</name>
+
+ <description>Jersey CDI test web application, this one uses Jersey (non JAX-RS) component injection</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x-transaction</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
new file mode 100644
index 0000000..16f3efb
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppEcho.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.enterprise.context.ApplicationScoped;
+
+
+/**
+ * Application specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@AppSpecific
+@ApplicationScoped
+public class AppEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "App: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
new file mode 100644
index 0000000..2bffeea
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedCtorInjectedResource.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-ctor-injected")
+public class AppScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ Provider<ContainerRequest> request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+
+ // to make weld happy
+ public AppScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public AppScopedCtorInjectedResource(@AppSpecific final EchoService echoService,
+ final Provider<ContainerRequest> request,
+ final ExceptionMappers mappers,
+ final Provider<MonitoringStatistics> stats,
+ final MyApplication.MyInjection customInjected) {
+ this.echoService = echoService;
+ this.request = request;
+ this.mappers = mappers;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") final String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
new file mode 100644
index 0000000..4c196d3
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppScopedFieldInjectedResource.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+import org.glassfish.jersey.tests.cdi.resources.MyApplication.MyInjection;
+
+/**
+ * CDI backed, application scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationScoped
+@Path("app-field-injected")
+public class AppScopedFieldInjectedResource {
+
+ // CDI injected
+ @Inject
+ @AppSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ Provider<ContainerRequest> request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injection
+ @Inject
+ MyInjection customInjected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.get().getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
new file mode 100644
index 0000000..000fc6d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/AppSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for application specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface AppSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
new file mode 100644
index 0000000..8745b22
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/EchoService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.inject.Qualifier;
+
+/**
+ * Simple echo service to test injections using {@link Qualifier}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface EchoService {
+
+ /**
+ * Provide an echoed response.
+ *
+ * @param s String to be echoed.
+ * @return echoed input.
+ */
+ public String echo(String s);
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
new file mode 100644
index 0000000..027c907
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyApplication.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.monitoring.MonitoringFeature;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends ResourceConfig {
+
+ public static class MyInjection {
+
+ private final String name;
+
+ public MyInjection(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public MyApplication() {
+ // JAX-RS resource classes
+ register(AppScopedFieldInjectedResource.class);
+ register(AppScopedCtorInjectedResource.class);
+ register(RequestScopedFieldInjectedResource.class);
+ register(RequestScopedCtorInjectedResource.class);
+
+ register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(new MyInjection("no way CDI would chime in")).to(MyInjection.class);
+ }
+ });
+
+ // Jersey monitoring
+ register(MonitoringFeature.class);
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java
new file mode 100644
index 0000000..362adf3
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/MyHk2TypesProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider;
+
+/**
+ * Tell Jersey CDI extension what types should be bridged from HK2 to CDI.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class MyHk2TypesProvider implements Hk2CustomBoundTypesProvider {
+
+ @Override
+ public Set<Type> getHk2Types() {
+ return new HashSet<Type>() {{
+ add(MyApplication.MyInjection.class);
+ }};
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
new file mode 100644
index 0000000..e0c26bc
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestEcho.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+/**
+ * Request specific echo implementation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestSpecific
+public class RequestEcho implements EchoService {
+
+ @Override
+ public String echo(String s) {
+ return "Request: " + s;
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
new file mode 100644
index 0000000..250c0d8
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedCtorInjectedResource.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource to be injected
+ * via it's constructor from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-ctor-injected")
+public class RequestScopedCtorInjectedResource {
+
+ // CDI injected
+ EchoService echoService;
+
+ // Jersey injected
+ ContainerRequest request;
+ ExceptionMappers mappers;
+ Provider<MonitoringStatistics> stats;
+
+ // Jersey/HK2 custom injected
+ MyApplication.MyInjection customInjected;
+
+ // to make weld happy
+ public RequestScopedCtorInjectedResource() {
+ }
+
+ @Inject
+ public RequestScopedCtorInjectedResource(@RequestSpecific EchoService echoService,
+ ContainerRequest request, ExceptionMappers mappers,
+ Provider<MonitoringStatistics> stats, MyApplication.MyInjection customInjected) {
+
+ this.echoService = echoService;
+ this.mappers = mappers;
+ this.request = request;
+ this.stats = stats;
+ this.customInjected = customInjected;
+ }
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
new file mode 100644
index 0000000..e762601
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestScopedFieldInjectedResource.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.monitoring.MonitoringStatistics;
+import org.glassfish.jersey.spi.ExceptionMappers;
+
+/**
+ * CDI backed, request scoped, JAX-RS resource.
+ * It's fields are injected from both CDI and Jersey HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("request-field-injected")
+public class RequestScopedFieldInjectedResource {
+
+ // built-in CDI bean
+ @Inject
+ BeanManager beanManager;
+
+ // CDI injected
+ @Inject
+ @RequestSpecific
+ EchoService echoService;
+
+ // Jersey injected
+ @Inject
+ ContainerRequest request;
+ @Inject
+ ExceptionMappers mappers;
+ @Inject
+ Provider<MonitoringStatistics> stats;
+
+ // Custom Jersey/HK2 injected
+ @Inject
+ MyApplication.MyInjection customInjected;
+
+ @GET
+ public String echo(@QueryParam("s") String s) {
+ return echoService.echo(s);
+ }
+
+ @GET
+ @Path("path/{param}")
+ public String getPath() {
+ return request.getPath(true);
+ }
+
+ @GET
+ @Path("mappers")
+ public String getMappers() {
+ return mappers.toString();
+ }
+
+ @GET
+ @Path("requestCount")
+ public String getStatisticsProperty() {
+ return String.valueOf(stats.get().snapshot().getRequestStatistics().getTimeWindowStatistics().get(0L).getRequestCount());
+ }
+
+ @GET
+ @Path("custom")
+ public String getCustom() {
+ return customInjected.getName();
+ }
+
+ @GET
+ @Path("bm")
+ public String getBm() {
+ return beanManager.toString();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
new file mode 100644
index 0000000..05f048d
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/java/org/glassfish/jersey/tests/cdi/resources/RequestSpecific.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for request specific echo service.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface RequestSpecific {
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider b/tests/integration/cdi-with-jersey-injection-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider
new file mode 100644
index 0000000..8ad35f8
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/resources/META-INF/services/org.glassfish.jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.resources.MyHk2TypesProvider
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ff67ca5
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <env-entry>
+ <env-entry-name>injectedResource</env-entry-name>
+ <env-entry-type>java.lang.Integer</env-entry-type>
+ <env-entry-value>10</env-entry-value>
+ </env-entry>
+</web-app>
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
new file mode 100644
index 0000000..1273dd1
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CdiTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+/**
+ * Test for CDI web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/cdi-with-jersey-injection-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CdiTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("cdi-with-jersey-injection-webapp").build();
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
new file mode 100644
index 0000000..4878426
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/CustomInjectionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test custom HK2 injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class CustomInjectionTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public CustomInjectionTest(String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side,
+ * and the custom bound instance gets injected.
+ */
+ @Test
+ public void testCustomHk2InjectionNull() {
+ WebTarget target = target().path(resource).path("custom");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("no way CDI would chime in"));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
new file mode 100644
index 0000000..4020db3
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/ExceptionMappersTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for exception mapper injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class ExceptionMappersTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource query parameter.
+ */
+ public ExceptionMappersTest(String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Check that for one no NPE happens on the server side, and for two
+ * the injected mappers remains the same across requests.
+ */
+ @Test
+ public void testMappersNotNull() {
+ WebTarget target = target().path(resource).path("mappers");
+ final Response firstResponse = target.request().get();
+ assertThat(firstResponse.getStatus(), equalTo(200));
+ String firstValue = firstResponse.readEntity(String.class);
+ assertThat(target.request().get(String.class), equalTo(firstValue));
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
new file mode 100644
index 0000000..f364be2
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/MonitoringTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for monitoring statistics injection.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class MonitoringTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected"},
+ {"app-ctor-injected"},
+ {"request-field-injected"},
+ {"request-ctor-injected"}
+ });
+ }
+
+ final String resource;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of resource to be tested.
+ */
+ public MonitoringTest(String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Make several requests and check the counter keeps incrementing.
+ *
+ * @throws Exception in case of unexpected test failure.
+ */
+ @Test
+ public void testRequestCount() throws Exception {
+ WebTarget target = target().path(resource).path("requestCount");
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ int start = Integer.decode(target.request().get(String.class));
+ for (int i = 1; i < 4; i++) {
+ Thread.sleep(1000); // this is to allow statistics on the server side to get updated
+ int next = Integer.decode(target.request().get(String.class));
+ assertThat(String.format("testing %s", resource), next, equalTo(start + i));
+ }
+ }
+}
diff --git a/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
new file mode 100644
index 0000000..ff41909
--- /dev/null
+++ b/tests/integration/cdi-with-jersey-injection-webapp/src/test/java/org/glassfish/jersey/tests/cdi/resources/RequestSensitiveTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resources;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test injection of request depending instances works as expected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class RequestSensitiveTest extends CdiTest {
+
+ @Parameterized.Parameters
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"app-field-injected", "alpha", "App: alpha"},
+ {"app-field-injected", "gogol", "App: gogol"},
+ {"app-field-injected", "elcaro", "App: elcaro"},
+ {"app-ctor-injected", "alpha", "App: alpha"},
+ {"app-ctor-injected", "gogol", "App: gogol"},
+ {"app-ctor-injected", "elcaro", "App: elcaro"},
+ {"request-field-injected", "alpha", "Request: alpha"},
+ {"request-field-injected", "gogol", "Request: gogol"},
+ {"request-field-injected", "oracle", "Request: oracle"},
+ {"request-ctor-injected", "alpha", "Request: alpha"},
+ {"request-ctor-injected", "gogol", "Request: gogol"},
+ {"request-ctor-injected", "oracle", "Request: oracle"}
+ });
+ }
+
+ final String resource, straight, echoed;
+
+ /**
+ * Construct instance with the above test data injected.
+ *
+ * @param resource uri of the resource to be tested.
+ * @param straight request specific input.
+ * @param echoed CDI injected service should produce this out of previous, straight, parameter.
+ */
+ public RequestSensitiveTest(String resource, String straight, String echoed) {
+ this.resource = resource;
+ this.straight = straight;
+ this.echoed = echoed;
+ }
+
+ @Test
+ public void testCdiInjection() {
+ String s = target().path(resource).queryParam("s", straight).request().get(String.class);
+ assertThat(s, equalTo(echoed));
+ }
+
+ @Test
+ public void testHk2Injection() {
+ String s = target().path(resource).path("path").path(straight).request().get(String.class);
+ assertThat(s, equalTo(String.format("%s/path/%s", resource, straight)));
+ }
+}
diff --git a/tests/integration/client-connector-provider/pom.xml b/tests/integration/client-connector-provider/pom.xml
new file mode 100644
index 0000000..465f8e6
--- /dev/null
+++ b/tests/integration/client-connector-provider/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>client-connector-provider</artifactId>
+ <packaging>jar</packaging>
+ <name>client-connector-provider</name>
+
+ <description>Client Connector provider test</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ </build>
+</project>
diff --git a/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProvider.java b/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProvider.java
new file mode 100644
index 0000000..5a4e70b
--- /dev/null
+++ b/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.client.connector.provider;
+
+import java.net.HttpURLConnection;
+
+import javax.ws.rs.client.Client;
+
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.internal.HttpUrlConnector;
+import org.glassfish.jersey.client.spi.Connector;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public final class CustomConnectorProvider extends HttpUrlConnectorProvider {
+
+ public static volatile boolean invoked = false;
+
+ @Override
+ protected Connector createHttpUrlConnector(Client client, ConnectionFactory connectionFactory, int chunkSize,
+ boolean fixLengthStreaming, boolean setMethodWorkaround) {
+
+ return new HttpUrlConnector(
+ client,
+ connectionFactory,
+ chunkSize,
+ fixLengthStreaming,
+ setMethodWorkaround) {
+
+ @Override
+ protected void secureConnection(JerseyClient client, HttpURLConnection uc) {
+ invoked = true;
+ }
+ };
+ }
+}
diff --git a/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/TestResource.java b/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/TestResource.java
new file mode 100644
index 0000000..f941b89
--- /dev/null
+++ b/tests/integration/client-connector-provider/src/main/java/org/glassfish/jersey/tests/integration/client/connector/provider/TestResource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.client.connector.provider;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("test")
+public class TestResource {
+
+ @GET
+ public String get() {
+ return "test";
+ }
+}
diff --git a/tests/integration/client-connector-provider/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider b/tests/integration/client-connector-provider/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider
new file mode 100644
index 0000000..b3bb97e
--- /dev/null
+++ b/tests/integration/client-connector-provider/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.client.connector.provider.CustomConnectorProvider
diff --git a/tests/integration/client-connector-provider/src/test/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProviderTest.java b/tests/integration/client-connector-provider/src/test/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProviderTest.java
new file mode 100644
index 0000000..dc4daf1
--- /dev/null
+++ b/tests/integration/client-connector-provider/src/test/java/org/glassfish/jersey/tests/integration/client/connector/provider/CustomConnectorProviderTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.client.connector.provider;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class CustomConnectorProviderTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(TestResource.class);
+ }
+
+ @Test
+ public void testInvoked() {
+ assertFalse(CustomConnectorProvider.invoked);
+
+ Response response = target().path("test").request("text/plain").get();
+ assertEquals(200, response.getStatus());
+
+ assertTrue(CustomConnectorProvider.invoked);
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/ear/pom.xml b/tests/integration/ejb-multimodule-reload/ear/pom.xml
new file mode 100644
index 0000000..09183cb
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/ear/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-reload-ear</artifactId>
+ <packaging>ear</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-reload-ear</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
+ <modules>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-war1</artifactId>
+ </webModule>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-war2</artifactId>
+ </webModule>
+ <ejbModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-lib</artifactId>
+ </ejbModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-war1</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-war2</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-reload-lib</artifactId>
+ <type>ejb</type>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/integration/ejb-multimodule-reload/lib/pom.xml b/tests/integration/ejb-multimodule-reload/lib/pom.xml
new file mode 100644
index 0000000..730d296
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-reload-lib</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-reload-lib</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ContainerListener.java b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ContainerListener.java
new file mode 100644
index 0000000..11de9c9
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ContainerListener.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib;
+
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+
+/**
+ * JAX-RS resource that keeps number of reloads.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Singleton
+public class ContainerListener extends AbstractContainerLifecycleListener {
+
+ @EJB EjbReloaderService reloader;
+
+ @Override
+ public void onStartup(final Container container) {
+ reloader.setContainer(container);
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/EjbReloaderService.java b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/EjbReloaderService.java
new file mode 100644
index 0000000..fc95ca8
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/EjbReloaderService.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib;
+
+import javax.ejb.Singleton;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.Container;
+
+/**
+ * Singleton EJB bean that is used to reload the first web application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+public class EjbReloaderService {
+
+ Container container;
+
+ public void reload() {
+ container.reload(newApp());
+ }
+
+ /**
+ * Create new resource config that contains {@link ReloadDetectionResource} singleton
+ * with current nano time, so that we can detect when the application has been initialized.
+ *
+ * @return new resource config.
+ */
+ private ResourceConfig newApp() {
+
+ ResourceConfig result = new ResourceConfig();
+ result.register(ReloadDetectionResource.createNewInstance());
+ result.register(ContainerListener.class);
+ return result;
+ }
+
+ /**
+ * Set the container to be reloaded. Invoked from {@link ContainerListener}.
+ *
+ * @param container to be reloaded.
+ */
+ public void setContainer(Container container) {
+ this.container = container;
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloadDetectionResource.java b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloadDetectionResource.java
new file mode 100644
index 0000000..95cbf5b
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloadDetectionResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.inject.Singleton;
+
+/**
+ * JAX-RS resource registered as a singleton
+ * allows to detect when application got initiated as the value
+ * returned from its getNano resource method
+ * will get adjusted with each reload.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("last-init-nano-time")
+public class ReloadDetectionResource {
+
+ final long ns = System.nanoTime();
+
+ private ReloadDetectionResource() {
+ // prevent instantiation
+ }
+
+ /**
+ * This is the only mean how to get a new instance of the resource.
+ *
+ * @return new reload detection resource.
+ */
+ public static final ReloadDetectionResource createNewInstance() {
+ return new ReloadDetectionResource();
+ }
+
+
+ @GET
+ public long getNano() {
+ return ns;
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloaderResource.java b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloaderResource.java
new file mode 100644
index 0000000..ff2ce6d
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/lib/ReloaderResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * JAX-RS resource used to reload the first application.
+ * This resource is only registered inside the second application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("reload")
+public class ReloaderResource {
+
+ @EJB EjbReloaderService ejbReloaderService;
+
+ @GET
+ public void reloadTheOtherApp() {
+ ejbReloaderService.reload();
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/lib/src/main/resources/META-INF/beans.xml b/tests/integration/ejb-multimodule-reload/lib/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..3b46d69
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/lib/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/ejb-multimodule-reload/pom.xml b/tests/integration/ejb-multimodule-reload/pom.xml
new file mode 100644
index 0000000..35fd46f
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>ejb-multimodule-reload</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-reload</name>
+
+ <description>
+ EJB Multi-Module Reload
+ </description>
+
+ <modules>
+ <module>ear</module>
+ <module>lib</module>
+ <module>war1</module>
+ <module>war2</module>
+ </modules>
+</project>
diff --git a/tests/integration/ejb-multimodule-reload/war1/pom.xml b/tests/integration/ejb-multimodule-reload/war1/pom.xml
new file mode 100644
index 0000000..f90e657
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war1/pom.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-reload-war1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-reload-war1</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ejb-multimodule-reload-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2.external</groupId>
+ <artifactId>javax.inject</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ </exclusion>
+ </exclusions>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/ejb-multimodule-reload/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/FirstApp.java b/tests/integration/ejb-multimodule-reload/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/FirstApp.java
new file mode 100644
index 0000000..f24d546
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war1/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/FirstApp.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.web1;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib.ContainerListener;
+import org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib.ReloadDetectionResource;
+
+/**
+ * Initial JAX-RS application for the first web application.
+ * This one will get reloaded.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/")
+public class FirstApp extends Application {
+
+ static final Set<Object> SINGLETONS = new HashSet<Object>() {{
+ add(ReloadDetectionResource.createNewInstance());
+ }};
+
+ static final Set<Class<?>> CLASSES = new HashSet<Class<?>>() {{
+ add(ContainerListener.class);
+ }};
+
+ @Override
+ public Set<Object> getSingletons() {
+ return SINGLETONS;
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return CLASSES;
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/war1/src/main/resources/META-INF/beans.xml b/tests/integration/ejb-multimodule-reload/war1/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war1/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/ejb-multimodule-reload/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/ReloadTest.java b/tests/integration/ejb-multimodule-reload/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/ReloadTest.java
new file mode 100644
index 0000000..4d854b0
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war1/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web1/ReloadTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.web1;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test reload functionality for two web app test case.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy ../ear/target/ejb-multimodule-reload-ear-*.ear
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ReloadTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new FirstApp();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testReload() {
+
+ final WebTarget nanosTarget = target().path("ejb-multimodule-reload-war1/last-init-nano-time");
+
+ final long nanos1 = _readInitTimeNanos(nanosTarget);
+ final long nanos2 = _readInitTimeNanos(nanosTarget);
+
+ assertThat(nanos2, is(equalTo(nanos1)));
+
+ // J-592 reproducer:
+
+// reload();
+//
+// final long nanos3 = _readInitTimeNanos(nanosTarget);
+// final long nanos4 = _readInitTimeNanos(nanosTarget);
+//
+// assertThat(nanos4, is(equalTo(nanos3)));
+// assertThat(nanos3, is(greaterThan(nanos2)));
+//
+// reload();
+//
+// final long nanos5 = _readInitTimeNanos(nanosTarget);
+// final long nanos6 = _readInitTimeNanos(nanosTarget);
+//
+// assertThat(nanos6, is(equalTo(nanos5)));
+// assertThat(nanos5, is(greaterThan(nanos4)));
+
+ // END: J-592 reproducer
+ }
+
+ private void reload() {
+ final WebTarget reloadTarget = target().path("ejb-multimodule-reload-war2/reload");
+ assertThat(reloadTarget.request().get().getStatus(), is(204));
+ }
+
+ private long _readInitTimeNanos(final WebTarget target) throws NumberFormatException {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ return Long.parseLong(response.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/war2/pom.xml b/tests/integration/ejb-multimodule-reload/war2/pom.xml
new file mode 100644
index 0000000..1a3bf25
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war2/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-reload-war2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-reload-war2</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ejb-multimodule-reload-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/ejb-multimodule-reload/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/SecondApp.java b/tests/integration/ejb-multimodule-reload/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/SecondApp.java
new file mode 100644
index 0000000..89d2304
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war2/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/SecondApp.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.web2;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.tests.integration.multimodule.ejb.reload.lib.ReloaderResource;
+
+/**
+ * JAX-RS application from which we are going to reload
+ * the other one.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/")
+public class SecondApp extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(ReloaderResource.class);
+ }};
+ }
+}
diff --git a/tests/integration/ejb-multimodule-reload/war2/src/main/resources/META-INF/beans.xml b/tests/integration/ejb-multimodule-reload/war2/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war2/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/ejb-multimodule-reload/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/JaxRsFromEjbLibraryTest.java b/tests/integration/ejb-multimodule-reload/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/JaxRsFromEjbLibraryTest.java
new file mode 100644
index 0000000..7dc32da
--- /dev/null
+++ b/tests/integration/ejb-multimodule-reload/war2/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/reload/web2/JaxRsFromEjbLibraryTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.reload.web2;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+/**
+ * Test for EJB web application resources. The JAX-RS resources come from bundled EJB library jar.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy ../ear/target/ejb-multimodule-ear-*.ear
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class JaxRsFromEjbLibraryTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new SecondApp();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("ejb-multimodule-war").path("resources").build();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testRequestCountGetsIncremented() {
+ final int requestCount1 = _nextCount(target().path("counter"));
+
+ final int requestCount2 = _nextCount(target().path("counter"));
+ assertThat(requestCount2, is(greaterThan(requestCount1)));
+
+ final int requestCount3 = _nextCount(target().path("stateless"));
+ assertThat(requestCount3, is(greaterThan(requestCount2)));
+
+ final int requestCount4 = _nextCount(target().path("stateless"));
+ assertThat(requestCount4, is(greaterThan(requestCount3)));
+
+ final int requestCount5 = _nextCount(target().path("stateful").path("count"));
+ assertThat(requestCount5, is(greaterThan(requestCount4)));
+
+ final int requestCount6 = _nextCount(target().path("stateful").path("count"));
+ assertThat(requestCount6, is(greaterThan(requestCount5)));
+
+ final int requestCount7 = _nextCount(target().path("war-stateless"));
+ assertThat(requestCount7, is(greaterThan(requestCount6)));
+
+ final int requestCount8 = _nextCount(target().path("war-stateless"));
+ assertThat(requestCount8, is(greaterThan(requestCount7)));
+ }
+
+ private int _nextCount(final WebTarget target) throws NumberFormatException {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ return Integer.parseInt(response.readEntity(String.class));
+ }
+
+ @Test
+ public void testUriInfoInjection() {
+ _testPath(target().path("counter").path("one"), "counter/one");
+ _testPath(target().path("counter").path("two"), "counter/two");
+ _testPath(target().path("stateless").path("three"), "stateless/three");
+ _testPath(target().path("stateless").path("four"), "stateless/four");
+ _testPath(target().path("war-stateless").path("five"), "war-stateless/five");
+ _testPath(target().path("war-stateless").path("six"), "war-stateless/six");
+ }
+
+ private void _testPath(final WebTarget target, final String expectedResult) {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+}
diff --git a/tests/integration/ejb-multimodule/ear/pom.xml b/tests/integration/ejb-multimodule/ear/pom.xml
new file mode 100644
index 0000000..742f13d
--- /dev/null
+++ b/tests/integration/ejb-multimodule/ear/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-ear</artifactId>
+ <packaging>ear</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-ear</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
+ <modules>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-war</artifactId>
+ </webModule>
+ <ejbModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-lib</artifactId>
+ </ejbModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-war</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>ejb-multimodule-lib</artifactId>
+ <type>ejb</type>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/integration/ejb-multimodule/ear/src/main/application/META-INF/MANIFEST.MF b/tests/integration/ejb-multimodule/ear/src/main/application/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..59499bc
--- /dev/null
+++ b/tests/integration/ejb-multimodule/ear/src/main/application/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+
diff --git a/tests/integration/ejb-multimodule/lib/pom.xml b/tests/integration/ejb-multimodule/lib/pom.xml
new file mode 100644
index 0000000..916ead4
--- /dev/null
+++ b/tests/integration/ejb-multimodule/lib/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-lib</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-lib</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/EjbCounterResource.java b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/EjbCounterResource.java
new file mode 100644
index 0000000..b1fcf20
--- /dev/null
+++ b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/EjbCounterResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.lib;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ejb.Singleton;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Singleton EJB counter bean as a JAX-RS resource.
+ * The bean is for one published as a standalone JAX-RS resource
+ * and for two used to inject other EJB based JAX-RS resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+@Path("counter")
+public class EjbCounterResource {
+
+ final AtomicInteger counter = new AtomicInteger();
+
+ @Context UriInfo ui;
+
+ @GET
+ public int getCount() {
+ return counter.incrementAndGet();
+ }
+
+ @Path("{ui}")
+ @GET
+ public String getUi() {
+ return ui != null ? ui.getPath() : "UriInfo is null";
+ }
+}
diff --git a/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatefulResource.java b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatefulResource.java
new file mode 100644
index 0000000..6250c2d
--- /dev/null
+++ b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatefulResource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.lib;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateful;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * JAX-RS resource backed with a stateful EJB bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateful
+@Path("stateful")
+public class StatefulResource {
+
+ @EJB EjbCounterResource counter;
+
+ @GET
+ @Path("count")
+ public int getCount() {
+ return counter.getCount();
+ }
+}
diff --git a/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatelessResource.java b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatelessResource.java
new file mode 100644
index 0000000..b349095
--- /dev/null
+++ b/tests/integration/ejb-multimodule/lib/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/lib/StatelessResource.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.lib;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * JAX-RS resource backed by a stateless EJB bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("stateless")
+public class StatelessResource {
+
+ @EJB EjbCounterResource counter;
+ @Context UriInfo uriInfo;
+
+ @GET
+ public int getCount() {
+ return counter.getCount();
+ }
+
+ @GET
+ @Path("{uriInfo}")
+ public String getPath() {
+ return uriInfo != null ? uriInfo.getPath() : "uri info is null";
+ }
+}
diff --git a/tests/integration/ejb-multimodule/pom.xml b/tests/integration/ejb-multimodule/pom.xml
new file mode 100644
index 0000000..78a39c6
--- /dev/null
+++ b/tests/integration/ejb-multimodule/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>ejb-multimodule</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration-ejb-multimodule</name>
+
+ <description>
+ EJB Multi-Module
+ </description>
+
+ <modules>
+ <module>ear</module>
+ <module>lib</module>
+ <module>war</module>
+ </modules>
+</project>
diff --git a/tests/integration/ejb-multimodule/war/pom.xml b/tests/integration/ejb-multimodule/war/pom.xml
new file mode 100644
index 0000000..8c40b68
--- /dev/null
+++ b/tests/integration/ejb-multimodule/war/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>ejb-multimodule-war</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-ejb-multimodule-war</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ejb-multimodule-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <!--archive>
+ <manifestEntries>
+ <Class-Path>ejb-lib-${project.version}.jar</Class-Path>
+ </manifestEntries>
+ </archive-->
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsConfiguration.java b/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsConfiguration.java
new file mode 100644
index 0000000..18ab4ce
--- /dev/null
+++ b/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.web1;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.tests.integration.multimodule.ejb.lib.EjbCounterResource;
+import org.glassfish.jersey.tests.integration.multimodule.ejb.lib.StatefulResource;
+import org.glassfish.jersey.tests.integration.multimodule.ejb.lib.StatelessResource;
+
+/**
+ * JAX-RS application resource configuration that includes only
+ * those JAX-RS components imported from EJB library jar.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("resources")
+public class JaxRsConfiguration extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(EjbCounterResource.class);
+ add(StatelessResource.class);
+ add(StatefulResource.class);
+ add(WarStatelessResource.class);
+ }};
+ }
+}
diff --git a/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/WarStatelessResource.java b/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/WarStatelessResource.java
new file mode 100644
index 0000000..008539d
--- /dev/null
+++ b/tests/integration/ejb-multimodule/war/src/main/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/WarStatelessResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.web1;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+
+import org.glassfish.jersey.tests.integration.multimodule.ejb.lib.EjbCounterResource;
+
+/**
+ * JAX-RS resource backed by a stateless EJB bean placed in WAR module.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Stateless
+@Path("war-stateless")
+public class WarStatelessResource {
+
+ @EJB EjbCounterResource counter;
+ @Context UriInfo uriInfo;
+
+ @GET
+ public int getCount() {
+ return counter.getCount();
+ }
+
+ @GET
+ @Path("{uriInfo}")
+ public String getPath() {
+ return uriInfo != null ? uriInfo.getPath() : "uri info is null";
+ }
+}
diff --git a/tests/integration/ejb-multimodule/war/src/main/webapp/index.jsp b/tests/integration/ejb-multimodule/war/src/main/webapp/index.jsp
new file mode 100644
index 0000000..d9c02e5
--- /dev/null
+++ b/tests/integration/ejb-multimodule/war/src/main/webapp/index.jsp
@@ -0,0 +1,31 @@
+<%--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JSP Page</title>
+ </head>
+ <body>
+ <h1>Hello World!</h1>
+ </body>
+</html>
diff --git a/tests/integration/ejb-multimodule/war/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsFromEjbLibraryTest.java b/tests/integration/ejb-multimodule/war/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsFromEjbLibraryTest.java
new file mode 100644
index 0000000..3eb6aa0
--- /dev/null
+++ b/tests/integration/ejb-multimodule/war/src/test/java/org/glassfish/jersey/tests/integration/multimodule/ejb/web1/JaxRsFromEjbLibraryTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.multimodule.ejb.web1;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+/**
+ * Test for EJB web application resources. The JAX-RS resources come from bundled EJB library jar.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy ../ear/target/ejb-multimodule-ear-*.ear
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class JaxRsFromEjbLibraryTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsConfiguration();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("ejb-multimodule-war").path("resources").build();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testRequestCountGetsIncremented() {
+ final int requestCount1 = _nextCount(target().path("counter"));
+
+ final int requestCount2 = _nextCount(target().path("counter"));
+ assertThat(requestCount2, is(greaterThan(requestCount1)));
+
+ final int requestCount3 = _nextCount(target().path("stateless"));
+ assertThat(requestCount3, is(greaterThan(requestCount2)));
+
+ final int requestCount4 = _nextCount(target().path("stateless"));
+ assertThat(requestCount4, is(greaterThan(requestCount3)));
+
+ final int requestCount5 = _nextCount(target().path("stateful").path("count"));
+ assertThat(requestCount5, is(greaterThan(requestCount4)));
+
+ final int requestCount6 = _nextCount(target().path("stateful").path("count"));
+ assertThat(requestCount6, is(greaterThan(requestCount5)));
+
+ final int requestCount7 = _nextCount(target().path("war-stateless"));
+ assertThat(requestCount7, is(greaterThan(requestCount6)));
+
+ final int requestCount8 = _nextCount(target().path("war-stateless"));
+ assertThat(requestCount8, is(greaterThan(requestCount7)));
+ }
+
+ private int _nextCount(final WebTarget target) throws NumberFormatException {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ return Integer.parseInt(response.readEntity(String.class));
+ }
+
+ @Test
+ public void testUriInfoInjection() {
+ _testPath(target().path("counter").path("one"), "counter/one");
+ _testPath(target().path("counter").path("two"), "counter/two");
+ _testPath(target().path("stateless").path("three"), "stateless/three");
+ _testPath(target().path("stateless").path("four"), "stateless/four");
+ _testPath(target().path("war-stateless").path("five"), "war-stateless/five");
+ _testPath(target().path("war-stateless").path("six"), "war-stateless/six");
+ }
+
+ private void _testPath(final WebTarget target, final String expectedResult) {
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), equalTo(expectedResult));
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/pom.xml b/tests/integration/ejb-test-webapp/pom.xml
new file mode 100644
index 0000000..6ca69fa
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>ejb-test-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-ejb-webapp</name>
+
+ <description>Jersey EJB test web application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1-b07</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AppResource.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AppResource.java
new file mode 100644
index 0000000..ba03d17
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AppResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * Test resource that exposes counter from the JAX-RS application subclass.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("app")
+public class AppResource {
+
+ @EJB MyApplication app;
+
+ @Path("count")
+ @GET
+ public int getCount() {
+ return app.incrementAndGetCount();
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncResource.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncResource.java
new file mode 100644
index 0000000..e5c67fb
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+import javax.ejb.EJB;
+
+/**
+ * @author Jan Algermissen
+ * @author Miroslav Fuksa
+ */
+@Path("async-test")
+public class AsyncResource {
+
+ @EJB
+ AsyncService asyncService;
+
+ @GET
+ @Path("sync")
+ public String synchronousGet() {
+ return "sync";
+ }
+
+ @GET
+ @Path("async")
+ public void asynchronousGet(@Suspended AsyncResponse ar) {
+ asyncService.getAsync(ar);
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncService.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncService.java
new file mode 100644
index 0000000..8ea1ac4
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/AsyncService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.util.logging.Logger;
+
+import javax.ejb.Asynchronous;
+import javax.ejb.Stateless;
+import javax.ws.rs.container.AsyncResponse;
+
+/**
+ * @author Jan Algermissen
+ * @author Miroslav Fuksa
+ */
+@Stateless
+public class AsyncService {
+ private static Logger LOG = Logger.getLogger(AsyncService.class.getName());
+
+ @Asynchronous
+ public void getAsync(AsyncResponse ar) {
+ ar.resume("async");
+ }
+}
+
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterBean.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterBean.java
new file mode 100644
index 0000000..3e43e59
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.ejb.Singleton;
+
+/**
+ * EJB singleton utilized as request counter in this test application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+public class CounterBean {
+
+ AtomicInteger counter = new AtomicInteger();
+
+ public int incrementAndGet() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterFilter.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterFilter.java
new file mode 100644
index 0000000..e67edc4
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CounterFilter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.io.IOException;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Response filter implemented as EJB bean. The filter adds Request-Count response header to each response.
+ * Another EJB singleton bean, CounterBean, is injected that holds the actual request count.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Stateless
+public class CounterFilter implements ContainerResponseFilter{
+
+ public static final String RequestCountHEADER = "Request-Count";
+
+ @EJB CounterBean counter;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ responseContext.getHeaders().add(RequestCountHEADER, counter.incrementAndGet());
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomBaseException.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomBaseException.java
new file mode 100644
index 0000000..fda6ed4
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomBaseException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+/**
+ * Custom exception. Part of JERSEY-2320 reproducer.
+ * This one serves as a base for other exceptions
+ * mapped by {@link EjbExceptionMapperOne} and {@link EjbExceptionMapperTwo}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomBaseException extends Exception {
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionOne.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionOne.java
new file mode 100644
index 0000000..8a71b6e
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionOne.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+/**
+ * Custom exception. Part of JERSEY-2320 reproducer.
+ * This one gets mapped by {@link EjbExceptionMapperOne}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomExceptionOne extends CustomBaseException {
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionTwo.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionTwo.java
new file mode 100644
index 0000000..021dbdc
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/CustomExceptionTwo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+/**
+ * Custom exception. Part of JERSEY-2320 reproducer.
+ * This one gets mapped by {@link EjbExceptionMapperTwo}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomExceptionTwo extends CustomBaseException {
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/Echo.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/Echo.java
new file mode 100644
index 0000000..1e544bb
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/Echo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.Remote;
+
+/**
+ * EJB remote interface. Part of the reproducer for GLASSFISH-16199.
+ * See also the other test case implemented by {@link RawEchoResource}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Remote
+public interface Echo {
+
+ String echo(String message);
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoBean.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoBean.java
new file mode 100644
index 0000000..7763ed8
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoBean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.Stateful;
+
+/**
+ * Session bean capable of returning an echoed message back.
+ * This is to prove EJB container is used in {@link EchoResource}
+ * and {@link RawEchoResource} resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateful
+public class EchoBean {
+
+ /**
+ * Prefix, {@value}, to be attached to each message processed by this bean.
+ */
+ public static final String PREFIX = "ECHOED: ";
+
+ /**
+ * Echo message.
+ *
+ * @param message to be echoed.
+ * @return incoming message prefixed with {@link #PREFIX}.
+ */
+ public String echo(final String message) {
+ return String.format("%s%s", PREFIX, message);
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoResource.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoResource.java
new file mode 100644
index 0000000..1414e32
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EchoResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.EJB;
+import javax.ejb.Local;
+import javax.ejb.Remote;
+import javax.ejb.Stateless;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * JAX-RS resource bean backed by an EJB session bean
+ * implementing EJB interface that is annotated with both {@link Local}
+ * and {@link Remote} annotations.
+ * Reproducible test case for GLASSFISH-16199.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("echo")
+public class EchoResource implements Echo {
+
+ @EJB EchoBean echoService;
+
+ @GET
+ @Override
+ public String echo(@QueryParam("message") String message) {
+ return echoService.echo(message);
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperBase.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperBase.java
new file mode 100644
index 0000000..715d481
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperBase.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ws.rs.ext.ExceptionMapper;
+
+/**
+ * JERSEY-2320 reproducer. {@link CustomBaseException} will get mapped
+ * to an ordinary response.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public abstract class EjbExceptionMapperBase<T extends CustomBaseException> implements ExceptionMapper<T> {
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperOne.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperOne.java
new file mode 100644
index 0000000..0b9a559
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperOne.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * JERSEY-2320 reproducer. {@link CustomExceptionOne} will get mapped
+ * to an ordinary response. We make sure the mapper gets injected properly
+ * by both Jersey runtime and EJB container.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+public class EjbExceptionMapperOne extends EjbExceptionMapperBase<CustomExceptionOne> {
+
+ public static final String RESPONSE_BODY = "custom exception one thrown";
+
+ @Context UriInfo uriInfo;
+ @EJB EchoBean echoBean;
+
+ @Override
+ public Response toResponse(final CustomExceptionOne exception) {
+ return Response.ok(RESPONSE_BODY)
+ .header("My-Location", uriInfo.getPath())
+ .header("My-Echo", echoBean.echo("1")).build();
+ }
+
+
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperTwo.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperTwo.java
new file mode 100644
index 0000000..61227e9
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/EjbExceptionMapperTwo.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * JERSEY-2320 reproducer. {@link CustomExceptionTwo} will get mapped
+ * to an ordinary response. We make sure the mapper gets injected properly
+ * by both Jersey runtime and EJB container.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+public class EjbExceptionMapperTwo extends EjbExceptionMapperBase<CustomExceptionTwo> {
+
+ @Context UriInfo uriInfo;
+ @EJB EchoBean echoBean;
+
+ public static final String RESPONSE_BODY = "custom exception two thrown";
+
+ @Override
+ public Response toResponse(final CustomExceptionTwo exception) {
+ return Response.ok(RESPONSE_BODY)
+ .header("My-Location", uriInfo.getPath())
+ .header("My-Echo", echoBean.echo("2")).build();
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/ExceptionEjbResource.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/ExceptionEjbResource.java
new file mode 100644
index 0000000..9a12454
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/ExceptionEjbResource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.ejb.EJBException;
+import javax.ejb.Singleton;
+
+/**
+ * EJB backed JAX-RS resource to test if a custom exception info makes it to the client.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Singleton
+@Path("exception")
+public class ExceptionEjbResource {
+
+ public static class MyCheckedException extends Exception {
+
+ public MyCheckedException(String message) {
+ super(message);
+ }
+ }
+
+ public static class MyRuntimeException extends RuntimeException {
+
+ public MyRuntimeException(String message) {
+ super(message);
+ }
+ }
+
+ public static final String EjbExceptionMESSAGE = "ejb exception thrown directly";
+ public static final String CheckedExceptionMESSAGE = "checked exception thrown directly";
+
+ @GET
+ @Path("ejb")
+ public String throwEjbException() {
+ throw new EJBException(EjbExceptionMESSAGE);
+ }
+
+ @GET
+ @Path("checked")
+ public String throwCheckedException() throws MyCheckedException {
+ throw new MyCheckedException(CheckedExceptionMESSAGE);
+ }
+
+ @GET
+ @Path("custom1/{p}")
+ public String throwCustomExceptionOne() throws CustomBaseException {
+ throw new CustomExceptionOne();
+ }
+
+ @GET
+ @Path("custom2/{p}")
+ public String throwCustomExceptionTwo() throws CustomBaseException {
+ throw new CustomExceptionTwo();
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/MyApplication.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/MyApplication.java
new file mode 100644
index 0000000..c9c84a0
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/MyApplication.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ejb.Singleton;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/rest")
+@Singleton
+public class MyApplication extends Application {
+
+ private AtomicInteger counter;
+
+ @Override
+ public Map<String, Object> getProperties() {
+ return new HashMap<String, Object>() {{
+ put("jersey.config.server.response.setStatusOverSendError", true);
+ }};
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+
+ this.counter = new AtomicInteger();
+
+ return new HashSet<Class<?>>() {{
+ add(AppResource.class);
+ add(ExceptionEjbResource.class);
+ add(EchoResource.class);
+ add(RawEchoResource.class);
+ add(CounterFilter.class);
+ add(AsyncResource.class);
+ add(EjbExceptionMapperOne.class);
+ add(EjbExceptionMapperTwo.class);
+ }};
+ }
+
+ public int incrementAndGetCount() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEcho.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEcho.java
new file mode 100644
index 0000000..5b53347
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEcho.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+/**
+ * Part of the reproducer for GLASSFISH-16199. This EJB business interface
+ * is being registered by an annotation on the EJB component class, {@link RawEchoResource}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface RawEcho {
+
+ String echo(String message);
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEchoResource.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEchoResource.java
new file mode 100644
index 0000000..bbbe77c
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/RawEchoResource.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import javax.ejb.EJB;
+import javax.ejb.Remote;
+import javax.ejb.Stateless;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+/**
+ * JAX-RS resource bean backed by an EJB session bean
+ * implementing EJB interface, {@link RawEcho}, that is registered using {@link Remote} annotations.
+ * Reproducible test case for GLASSFISH-16199.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@Path("raw-echo")
+@Remote(RawEcho.class)
+public class RawEchoResource {
+
+ @EJB EchoBean echoService;
+
+ @GET
+ public String echo(@QueryParam("message") String message) {
+ return echoService.echo(message);
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/StandaloneServlet.java b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/StandaloneServlet.java
new file mode 100644
index 0000000..29e9ad5
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/main/java/org/glassfish/jersey/tests/ejb/resources/StandaloneServlet.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.io.IOException;
+
+import javax.ejb.EJB;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Standalone Servlet instance that has nothing to do with Jersey.
+ * It helps to compare Jersey and non-Jersey specific exception handling
+ * processing.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@WebServlet(name = "StandaloneServlet", urlPatterns = {"/servlet"})
+public class StandaloneServlet extends HttpServlet {
+
+ static final String ThrowCheckedExceptionACTION = "throwCheckedException";
+ static final String ThrowEjbExceptionACTION = "throwEjbException";
+
+ @EJB ExceptionEjbResource ejbResource;
+
+ /**
+ * Handles the HTTP <code>GET</code> method.
+ *
+ * @param request servlet request.
+ * @param response servlet response.
+ * @throws ServletException if a servlet-specific error occurs.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ final String action = request.getParameter("action");
+
+ if (ThrowCheckedExceptionACTION.equals(action)) {
+ try {
+ ejbResource.throwCheckedException();
+ } catch (ExceptionEjbResource.MyCheckedException ex) {
+ throw new ServletException(ex);
+ }
+ }
+
+ if (ThrowEjbExceptionACTION.equals(action)) {
+ ejbResource.throwEjbException();
+ }
+
+ sayHello(response);
+ }
+
+ private void sayHello(HttpServletResponse response) throws IOException {
+ response.setHeader("Content-type", "text/plain");
+ response.getOutputStream().print(
+ String.format("Use action parameter to specify exception."
+ + " \nSupported options: %s, %s.", ThrowCheckedExceptionACTION, ThrowEjbExceptionACTION));
+ }
+}
diff --git a/tests/integration/ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/ejb/resources/EjbTest.java b/tests/integration/ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/ejb/resources/EjbTest.java
new file mode 100644
index 0000000..a588cf6
--- /dev/null
+++ b/tests/integration/ejb-test-webapp/src/test/java/org/glassfish/jersey/tests/ejb/resources/EjbTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.ejb.resources;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
+
+/**
+ * Test for EJB web application resources.
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy target/ejb-test-webapp
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EjbTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("ejb-test-webapp").build();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(LoggingFeature.class);
+ }
+
+ @Test
+ public void testEjbException() {
+ final Response jerseyResponse = target().path("rest/exception/ejb").request().get();
+ _check500Response(jerseyResponse, ExceptionEjbResource.EjbExceptionMESSAGE);
+
+ final Response servletResponse =
+ target().path("servlet")
+ .queryParam("action", StandaloneServlet.ThrowEjbExceptionACTION).request().get();
+ _check500Response(servletResponse, ExceptionEjbResource.EjbExceptionMESSAGE);
+ }
+
+ @Test
+ public void testCheckedException() {
+ final Response jerseyResponse = target().path("rest/exception/checked").request().get();
+ _check500Response(jerseyResponse, ExceptionEjbResource.CheckedExceptionMESSAGE);
+
+ final Response servletResponse =
+ target().path("servlet")
+ .queryParam("action", StandaloneServlet.ThrowCheckedExceptionACTION).request().get();
+ _check500Response(servletResponse, ExceptionEjbResource.CheckedExceptionMESSAGE);
+ }
+
+ @Test
+ public void testCustomException1() {
+ Response jerseyResponse = target().path("rest/exception/custom1/big").request().get();
+ assertThat(jerseyResponse.getStatus(), is(200));
+ assertThat(jerseyResponse.readEntity(String.class), is(EjbExceptionMapperOne.RESPONSE_BODY));
+ assertThat(jerseyResponse.getHeaderString("My-Location"), is("exception/custom1/big"));
+ assertThat(jerseyResponse.getHeaderString("My-Echo"), is("ECHOED: 1"));
+
+ jerseyResponse = target().path("rest/exception/custom1/one").request().get();
+ assertThat(jerseyResponse.getStatus(), is(200));
+ assertThat(jerseyResponse.readEntity(String.class), is(EjbExceptionMapperOne.RESPONSE_BODY));
+ assertThat(jerseyResponse.getHeaderString("My-Location"), is("exception/custom1/one"));
+ assertThat(jerseyResponse.getHeaderString("My-Echo"), is("ECHOED: 1"));
+ }
+
+ @Test
+ public void testCustomException2() {
+ Response jerseyResponse = target().path("rest/exception/custom2/small").request().get();
+ assertThat(jerseyResponse.getStatus(), is(200));
+ assertThat(jerseyResponse.readEntity(String.class), is(EjbExceptionMapperTwo.RESPONSE_BODY));
+ assertThat(jerseyResponse.getHeaderString("My-Location"), is("exception/custom2/small"));
+ assertThat(jerseyResponse.getHeaderString("My-Echo"), is("ECHOED: 2"));
+
+ jerseyResponse = target().path("rest/exception/custom2/one").request().get();
+ assertThat(jerseyResponse.getStatus(), is(200));
+ assertThat(jerseyResponse.readEntity(String.class), is(EjbExceptionMapperTwo.RESPONSE_BODY));
+ assertThat(jerseyResponse.getHeaderString("My-Location"), is("exception/custom2/one"));
+ assertThat(jerseyResponse.getHeaderString("My-Echo"), is("ECHOED: 2"));
+ }
+
+ @Test
+ public void testRemoteLocalEJBInterface() {
+
+ final String message = "Hi there";
+ final Response response = target().path("rest/echo").queryParam("message", message).request().get();
+
+ assertThat(response.getStatus(), is(200));
+
+ final String responseMessage = response.readEntity(String.class);
+
+ assertThat(responseMessage, startsWith(EchoBean.PREFIX));
+ assertThat(responseMessage, endsWith(message));
+ }
+
+ @Test
+ public void testRemoteAnnotationRegisteredEJBInterface() {
+
+ final String message = "Hi there";
+ final Response response = target().path("rest/raw-echo").queryParam("message", message).request().get();
+
+ assertThat(response.getStatus(), is(200));
+
+ final String responseMessage = response.readEntity(String.class);
+
+ assertThat(responseMessage, startsWith(EchoBean.PREFIX));
+ assertThat(responseMessage, endsWith(message));
+ }
+
+ @Test
+ public void testRequestCountGetsIncremented() {
+
+ final Response response1 = target().path("rest/echo").queryParam("message", "whatever").request().get();
+ assertThat(response1.getStatus(), is(200));
+ final String counterHeader1 = response1.getHeaderString(CounterFilter.RequestCountHEADER);
+ final int requestCount1 = Integer.parseInt(counterHeader1);
+
+ final Response response2 = target().path("rest/echo").queryParam("message", requestCount1).request().get();
+ assertThat(response2.getStatus(), is(200));
+ final int requestCount2 = Integer.parseInt(response2.getHeaderString(CounterFilter.RequestCountHEADER));
+
+ assertThat(requestCount2, is(greaterThan(requestCount1)));
+ }
+
+
+ @Test
+ public void testSync() {
+ final Response response = target().path("rest/async-test/sync").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("sync"));
+ }
+
+ @Test
+ public void testAsync() {
+ final Response response = target().path("rest/async-test/async").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("async"));
+ }
+
+ @Test
+ public void testAppIsEjbSingleton() {
+
+ int c1 = target().path("rest/app/count").request().get(Integer.class);
+ int c2 = target().path("rest/app/count").request().get(Integer.class);
+ int c3 = target().path("rest/app/count").request().get(Integer.class);
+
+ assertThat("the first count should be less than the second one", c1, is(lessThan(c2)));
+ assertThat("the second count should be less than the third one", c2, is(lessThan(c3)));
+ }
+
+ private void _check500Response(final Response response, final String expectedSubstring) {
+ assertThat(response.getStatus(), is(500));
+ assertThat(response.readEntity(String.class), containsString(expectedSubstring));
+ }
+}
diff --git a/tests/integration/j-376/pom.xml b/tests/integration/j-376/pom.xml
new file mode 100644
index 0000000..4908e7c
--- /dev/null
+++ b/tests/integration/j-376/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>j-376</artifactId>
+ <packaging>jar</packaging>
+ <name>j-376-reproducer</name>
+
+ <description>Jersey test web application - J-376 reproducer</description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <scope>compile</scope>
+ <version>1.1.0.Final</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.grizzly</groupId>
+ <artifactId>grizzly-http-server</artifactId>
+ <version>2.3.16</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.glassfish.jersey.tests.integration.j376.GrizzlyApp</mainClass>
+ <classpathScope>test</classpathScope>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedBean.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedBean.java
new file mode 100644
index 0000000..1f5e78e
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedBean.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+
+/**
+ * Test {@code ApplicationScoped} bean to be injected to the test resource, while another {@code RequestScoped}
+ * bean being injected into this class.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@ApplicationScoped
+public class ApplicationScopedBean {
+
+ /** Request scoped bean injected via CDI */
+ @Inject
+ private SecondBean bean;
+
+ /** JAX-RS {@code Context} injection of request {@code UriInfo} */
+ @Context
+ private UriInfo uri;
+
+ private String name = "ApplicationScopedBean";
+
+ public String getMessage() {
+ return name + ":" + bean.getMessage();
+ }
+
+ public String getUri() {
+ return uri.getPath();
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedResource.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedResource.java
new file mode 100644
index 0000000..b0bf055
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ApplicationScopedResource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Resource to test CDI injection into {@code ApplicationScoped} JAX-RS resource.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("appScope")
+@ApplicationScoped
+public class ApplicationScopedResource {
+
+ /** Application scoped CDI injected bean */
+ @Inject
+ private ApplicationScopedBean appScoped;
+
+ /** Request scoped CDI injected bean */
+ @Inject
+ private SecondBean reqScoped;
+
+ /** Bean containing form parameters injected by JAX-RS */
+ @Inject
+ @BeanParam
+ private FormDataBean bean;
+
+ @POST
+ @Produces("text/plain")
+ public String get() {
+ return bean.getName() + ":" + bean.getAge() + ":"
+ + bean.getInjectedBean().getMessage() + ":" + bean.getInjectedPath();
+ }
+
+ @GET
+ @Path("msg")
+ @Produces("text/plain")
+ public String testAppScoped() {
+ return appScoped.getMessage();
+ }
+
+ @GET
+ @Path("uri")
+ public String getUri() {
+ return appScoped.getUri();
+ }
+
+ @GET
+ @Path("req")
+ public String getMessage() {
+ return reqScoped.getMessage();
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ConstructorInjectionResource.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ConstructorInjectionResource.java
new file mode 100644
index 0000000..a016733
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/ConstructorInjectionResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.validation.Valid;
+
+/**
+ * Resource to test CDI injection into JAX-RS resource via constructor parameter.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("constructor")
+@RequestScoped
+public class ConstructorInjectionResource {
+
+ private FormDataBean bean;
+
+ public ConstructorInjectionResource() {
+ }
+
+ @Inject
+ public ConstructorInjectionResource(@Valid @BeanParam final FormDataBean form) {
+ bean = form;
+ }
+
+ @POST
+ @Produces("text/plain")
+ public String get() {
+ return bean.getName() + ":" + bean.getAge() + ":"
+ + bean.getInjectedBean().getMessage() + ":" + bean.getInjectedPath();
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FieldInjectionResource.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FieldInjectionResource.java
new file mode 100644
index 0000000..84c6ec5
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FieldInjectionResource.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.validation.Valid;
+import javax.ws.rs.BeanParam;
+
+/**
+ * Resource to test CDI injection into JAX-RS resource via field.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("field")
+@RequestScoped
+public class FieldInjectionResource {
+
+ /** CDI injected request scoped field */
+ @Inject
+ @Valid
+ @BeanParam
+ private FormDataBean bean;
+
+ /** CDI injected applciation scoped bean */
+ @Inject
+ private ApplicationScopedBean appScoped;
+
+ /**
+ * Return string containing of fields from the injected non JAX-RS request scoped bean,
+ * path injected into it via {@code Context} annotation and another bean injected into it.
+ *
+ * Shows, that {@code Inject} and {@code Context} annotations can be used on one particular non JAX-RS class.
+ **/
+ @POST
+ @Produces("text/plain")
+ public String get() {
+ return bean.getName() + ":" + bean.getAge() + ":"
+ + bean.getInjectedBean().getMessage() + ":" + bean.getInjectedPath();
+ }
+
+ /** Return string from the {@code ApplicationScoped} non JAX_RS bean injected into this JAX-RS resource. */
+ @GET
+ @Path("appScoped")
+ @Produces("text/plain")
+ public String getMessage() {
+ return appScoped.getMessage();
+ }
+
+ /**
+ * Return path injected via {@code Context} annotation into {@code ApplicationScoped} non JAX-RS bean, that is
+ * further injected into this JAX-RS resource via CDI.
+ */
+ @GET
+ @Path("appScopedUri")
+ public String getUri() {
+ return appScoped.getUri();
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FormDataBean.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FormDataBean.java
new file mode 100644
index 0000000..819c498
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/FormDataBean.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * Test bean containingboth JAX-RS and CDI injection points.
+ */
+@RequestScoped
+public class FormDataBean {
+
+ private String injectedPath = null;
+
+ @NotNull
+ @Size(min = 4)
+ @FormParam("name")
+ private String name;
+
+ @Min(18)
+ @FormParam("age")
+ private int age;
+
+ @Inject
+ private SecondBean injectedBean;
+
+ @Context
+ private UriInfo uri;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ /**
+ * Exposes the state of injected {@code UriInfo} in the time of the call of {@link javax.annotation.PostConstruct}
+ * annotated method. The returned value will be used in test to ensure, that {@code UriInfo} is injected in time
+ *
+ * @return path injected via {@code UriInfo} at the time-point of the {@link #postConstruct()} method call.
+
+ */
+ public String getInjectedPath() {
+ return injectedPath;
+ }
+
+ public SecondBean getInjectedBean() {
+ return injectedBean;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ this.injectedPath = uri.getPath();
+ }
+
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/GrizzlyApp.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/GrizzlyApp.java
new file mode 100644
index 0000000..3de6d9c
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/GrizzlyApp.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.jboss.weld.environment.se.Weld;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * CDI Test App launcher. Starts the Grizzly server and initializes weld.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class GrizzlyApp {
+
+ private static Weld weld;
+ private static HttpServer server;
+
+ private static final URI BASE_URI = URI.create("http://localhost:8080/j376/");
+
+ public static void main(String[] args) {
+ try {
+ System.out.println("Jersey CDI Test App");
+
+ start();
+
+ System.out.println(String.format("Application started.\nTry out %s%s\nHit enter to stop it...",
+ BASE_URI, "application.wadl"));
+ System.in.read();
+ stop();
+ } catch (IOException ex) {
+ Logger.getLogger(GrizzlyApp.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ }
+
+ protected static void stop() {
+ server.shutdownNow();
+ weld.shutdown();
+ }
+
+ protected static void start() {
+ weld = new Weld();
+ weld.initialize();
+
+ server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, createJaxRsApp(), true);
+ }
+
+ public static URI getBaseUri() {
+ return BASE_URI;
+ }
+
+ public static ResourceConfig createJaxRsApp() {
+ return new ResourceConfig(new MyApplication().getClasses());
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MethodInjectionResource.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MethodInjectionResource.java
new file mode 100644
index 0000000..3f19676
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MethodInjectionResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.validation.Valid;
+
+/**
+ * Resource to test CDI injection into JAX-RS resource via setter.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("method")
+@RequestScoped
+public class MethodInjectionResource {
+
+ private FormDataBean bean;
+
+ @Inject
+ public void setFormDataBean(@Valid @BeanParam final FormDataBean form) {
+ bean = form;
+ }
+
+ @POST
+ @Produces("text/plain")
+ public String get() {
+ return bean.getName() + ":" + bean.getAge() + ":"
+ + bean.getInjectedBean().getMessage() + ":" + bean.getInjectedPath();
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MyApplication.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MyApplication.java
new file mode 100644
index 0000000..4ec0beb
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/MyApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * JAX-RS Application subclass, defines the test application resources.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@ApplicationPath("/*")
+public class MyApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<>();
+ classes.add(MethodInjectionResource.class);
+ classes.add(ConstructorInjectionResource.class);
+ classes.add(FieldInjectionResource.class);
+ classes.add(ApplicationScopedResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/SecondBean.java b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/SecondBean.java
new file mode 100644
index 0000000..2e5ead4
--- /dev/null
+++ b/tests/integration/j-376/src/main/java/org/glassfish/jersey/tests/integration/j376/SecondBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Bean to be injected into another bean by CDI.
+ *
+ * The purpose is to test, that CDI and hk2 injections are working together so that one class be injected by
+ * both CDI and Jersey/hk2.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RequestScoped
+public class SecondBean {
+ private String message = "Hello";
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/tests/integration/j-376/src/main/resources/META-INF/beans.xml b/tests/integration/j-376/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..3b46d69
--- /dev/null
+++ b/tests/integration/j-376/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/j-376/src/test/java/org/glassfish/jersey/tests/integration/j376/J376Test.java b/tests/integration/j-376/src/test/java/org/glassfish/jersey/tests/integration/j376/J376Test.java
new file mode 100644
index 0000000..fa39021
--- /dev/null
+++ b/tests/integration/j-376/src/test/java/org/glassfish/jersey/tests/integration/j376/J376Test.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j376;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class J376Test {
+ final Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target(GrizzlyApp.getBaseUri());
+
+ @BeforeClass
+ public static void setUpTest() {
+ GrizzlyApp.start();
+ }
+
+ @AfterClass
+ public static void tearDownTest() {
+ GrizzlyApp.stop();
+ }
+
+ @Test
+ public void testConstructorInjection() {
+ final String response = target.path("constructor").request().post(Entity.entity("name=John&age=32",
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
+
+ assertEquals("John:32:Hello:constructor", response);
+ }
+
+ @Test
+ public void testFieldInjection() {
+ final String response = target.path("field").request().post(Entity.entity("name=Bill&age=21",
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
+
+ assertEquals("Bill:21:Hello:field", response);
+ }
+
+ @Test
+ public void testMethodInjection() {
+ final String response = target.path("method").request().post(Entity.entity("name=Mike&age=42",
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
+
+ assertEquals("Mike:42:Hello:method", response);
+ }
+
+ @Test
+ public void testAppScopedBeanInReqScopedResource() {
+ final String response = target.path("field/appScoped").request().get(String.class);
+ assertEquals("ApplicationScopedBean:Hello", response);
+ }
+
+ @Test
+ public void testAppScopedResource() {
+ String response = target.path("appScope/msg").request().get(String.class);
+ assertEquals("ApplicationScopedBean:Hello", response);
+ response = target.path("appScope/uri").request().get(String.class);
+ assertEquals("appScope/uri", response);
+ response = target.path("appScope/req").request().get(String.class);
+ assertEquals("Hello", response);
+ }
+
+ @Test
+ public void testBeanParamInAppScoped() {
+ final String response = target.path("appScope").request().post(Entity.entity("name=John&age=35",
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
+
+ assertEquals("John:35:Hello:appScope", response);
+ }
+
+ @Test
+ public void testContextInjectionInAppScopedBean() {
+ final String response = target.path("field/appScopedUri").request().get(String.class);
+ assertEquals("field/appScopedUri", response);
+
+ }
+}
diff --git a/tests/integration/j-441/ear/pom.xml b/tests/integration/j-441/ear/pom.xml
new file mode 100644
index 0000000..ffeb59f
--- /dev/null
+++ b/tests/integration/j-441/ear/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <artifactId>j-441-ear</artifactId>
+ <packaging>ear</packaging>
+
+ <name>jersey-tests-integration-j-441-ear</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
+ <modules>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-441-war1</artifactId>
+ <contextRoot>/one</contextRoot>
+ </webModule>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-441-war2</artifactId>
+ <contextRoot>/two</contextRoot>
+ </webModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-441-war1</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-441-war2</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/integration/j-441/pom.xml b/tests/integration/j-441/pom.xml
new file mode 100644
index 0000000..e8109bf
--- /dev/null
+++ b/tests/integration/j-441/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>j-441</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration-j-441</name>
+
+ <description>
+ J-441 Reproducer: Two WARs with enabled CDI in an EAR.
+ </description>
+
+ <modules>
+ <module>ear</module>
+ <module>war1</module>
+ <module>war2</module>
+ </modules>
+</project>
diff --git a/tests/integration/j-441/war1/pom.xml b/tests/integration/j-441/war1/pom.xml
new file mode 100644
index 0000000..067ef5e
--- /dev/null
+++ b/tests/integration/j-441/war1/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>j-441-war1</artifactId>
+ <packaging>war</packaging>
+
+ <name>jersey-tests-integration-j-441-war1</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CdiResource.java b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CdiResource.java
new file mode 100644
index 0000000..33ce8da
--- /dev/null
+++ b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CdiResource.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.one;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+/**
+ * CDI backed JAX-RS resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/test")
+@RequestScoped
+public class CdiResource {
+
+ @Context
+ private ServletContext scField;
+
+ private ServletContext scCtorParam;
+
+ /* to make CDI happy */
+ public CdiResource() {
+ }
+
+ @Inject
+ public CdiResource(@Context final ServletContext sc) {
+ this.scCtorParam = sc;
+ }
+
+ @GET
+ @Path("ctor-param")
+ public String getCtorParam() {
+ return scCtorParam.getContextPath();
+ }
+
+ @GET
+ @Path("method-param")
+ public String getMethodParam(@Context final ServletContext sc) {
+ return sc.getContextPath();
+ }
+
+ @GET
+ @Path("field")
+ public String getField() {
+ return scField.getContextPath();
+ }
+
+ @GET
+ @Path("exception")
+ public String getException() throws Exception {
+ throw new Exception() {};
+ }
+}
diff --git a/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CustomExceptionMapper.java b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CustomExceptionMapper.java
new file mode 100644
index 0000000..d5aa71c
--- /dev/null
+++ b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/CustomExceptionMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.one;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.servlet.ServletContext;
+
+/**
+ * JAX-RS provider added just to make sure the application
+ * deploys fine. Since JAX-RS providers get initialized
+ * at Jersey bootstrapping phase, we would get a deploy
+ * error if something went wrong.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomExceptionMapper implements ExceptionMapper<Exception> {
+
+ @Context
+ private ServletContext sc;
+
+ public Response toResponse(final Exception ex) {
+ return Response.status(200).entity(sc.getContextPath()).build();
+ }
+}
diff --git a/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/MyApplication.java b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/MyApplication.java
new file mode 100644
index 0000000..073b84c
--- /dev/null
+++ b/tests/integration/j-441/war1/src/main/java/org/glassfish/jersey/tests/integration/j441/one/MyApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.one;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Test case to ensure proper WAR isolation on Jersey level.
+ * Define JAX-RS application containing a simple CDI backed JAX-RS resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/")
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ super(CdiResource.class, CustomExceptionMapper.class);
+ }
+}
diff --git a/tests/integration/j-441/war1/src/main/webapp/WEB-INF/beans.xml b/tests/integration/j-441/war1/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..93cfed7
--- /dev/null
+++ b/tests/integration/j-441/war1/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
diff --git a/tests/integration/j-441/war1/src/test/java/org/glassfish/jersey/tests/integration/j441/one/ContextPathTest.java b/tests/integration/j-441/war1/src/test/java/org/glassfish/jersey/tests/integration/j441/one/ContextPathTest.java
new file mode 100644
index 0000000..285859e
--- /dev/null
+++ b/tests/integration/j-441/war1/src/test/java/org/glassfish/jersey/tests/integration/j441/one/ContextPathTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.one;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * This is to make sure two Jersey wars are separated well in a single ear.
+ *
+ * @author Michal Gajdos
+ */
+public class ContextPathTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testFieldInjection() {
+ assertThat(target("one/test/field").request().get(String.class), is("/one"));
+ }
+
+ @Test
+ public void testConstructorInjection() {
+ assertThat(target("one/test/ctor-param").request().get(String.class), is("/one"));
+ }
+
+ @Test
+ public void testMethodInjection() {
+ assertThat(target("one/test/method-param").request().get(String.class), is("/one"));
+ }
+
+ @Test
+ public void testExceptionMapperInjection() {
+ assertThat(target("one/test/exception").request().get(String.class), is("/one"));
+ }
+}
diff --git a/tests/integration/j-441/war2/pom.xml b/tests/integration/j-441/war2/pom.xml
new file mode 100644
index 0000000..cd385ad
--- /dev/null
+++ b/tests/integration/j-441/war2/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>j-441-war2</artifactId>
+ <packaging>war</packaging>
+
+ <name>jersey-tests-integration-j-441-war2</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CdiResource.java b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CdiResource.java
new file mode 100644
index 0000000..0629273
--- /dev/null
+++ b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CdiResource.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.two;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+/**
+ * CDI backed JAX-RS resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/test")
+@RequestScoped
+public class CdiResource {
+
+ @Context
+ private ServletContext scField;
+
+ private ServletContext scCtorParam;
+
+ /* to make CDI happy */
+ public CdiResource() {
+ }
+
+ @Inject
+ public CdiResource(@Context final ServletContext sc) {
+ this.scCtorParam = sc;
+ }
+
+ @GET
+ @Path("ctor-param")
+ public String getCtorParam() {
+ return scCtorParam.getContextPath();
+ }
+
+ @GET
+ @Path("method-param")
+ public String getMethodParam(@Context final ServletContext sc) {
+ return sc.getContextPath();
+ }
+
+ @GET
+ @Path("field")
+ public String getField() {
+ return scField.getContextPath();
+ }
+
+ @GET
+ @Path("exception")
+ public String getException() throws Exception {
+ throw new Exception() {};
+ }
+}
diff --git a/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CustomExceptionMapper.java b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CustomExceptionMapper.java
new file mode 100644
index 0000000..0544100
--- /dev/null
+++ b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/CustomExceptionMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.two;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import javax.servlet.ServletContext;
+
+/**
+ * JAX-RS provider added just to make sure the application
+ * deploys fine. Since JAX-RS providers get initialized
+ * at Jersey bootstrapping phase, we would get a deploy
+ * error if something went wrong.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class CustomExceptionMapper implements ExceptionMapper<Exception> {
+
+ @Context
+ private ServletContext sc;
+
+ public Response toResponse(final Exception ex) {
+ return Response.status(200).entity(sc.getContextPath()).build();
+ }
+}
diff --git a/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/MyApplication.java b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/MyApplication.java
new file mode 100644
index 0000000..df6d3e3
--- /dev/null
+++ b/tests/integration/j-441/war2/src/main/java/org/glassfish/jersey/tests/integration/j441/two/MyApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.two;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Test case to ensure proper WAR isolation on Jersey level.
+ * Define JAX-RS application containing a simple CDI backed JAX-RS resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/")
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ super(CdiResource.class, CustomExceptionMapper.class);
+ }
+}
diff --git a/tests/integration/j-441/war2/src/main/webapp/WEB-INF/beans.xml b/tests/integration/j-441/war2/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..93cfed7
--- /dev/null
+++ b/tests/integration/j-441/war2/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
diff --git a/tests/integration/j-441/war2/src/test/java/org/glassfish/jersey/tests/integration/j441/two/ContextPathTest.java b/tests/integration/j-441/war2/src/test/java/org/glassfish/jersey/tests/integration/j441/two/ContextPathTest.java
new file mode 100644
index 0000000..bb4f68b
--- /dev/null
+++ b/tests/integration/j-441/war2/src/test/java/org/glassfish/jersey/tests/integration/j441/two/ContextPathTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j441.two;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * This is to make sure two Jersey wars are separated well in a single ear.
+ *
+ * @author Michal Gajdos
+ */
+public class ContextPathTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testFieldInjection() {
+ assertThat(target("two/test/field").request().get(String.class), is("/two"));
+ }
+
+ @Test
+ public void testConstructorInjection() {
+ assertThat(target("two/test/ctor-param").request().get(String.class), is("/two"));
+ }
+
+ @Test
+ public void testMethodInjection() {
+ assertThat(target("two/test/method-param").request().get(String.class), is("/two"));
+ }
+
+ @Test
+ public void testExceptionMapperInjection() {
+ assertThat(target("two/test/exception").request().get(String.class), is("/two"));
+ }
+}
diff --git a/tests/integration/j-59/ear/pom.xml b/tests/integration/j-59/ear/pom.xml
new file mode 100644
index 0000000..fdce31a
--- /dev/null
+++ b/tests/integration/j-59/ear/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>j-59-ear</artifactId>
+ <packaging>ear</packaging>
+ <name>jersey-tests-integration-j-59-ear</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
+ <modules>
+ <webModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-59-cdi-war</artifactId>
+ </webModule>
+ <ejbModule>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-59-ejb-lib</artifactId>
+ </ejbModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-59-cdi-war</artifactId>
+ <type>war</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>j-59-ejb-lib</artifactId>
+ <type>ejb</type>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/integration/j-59/lib/pom.xml b/tests/integration/j-59/lib/pom.xml
new file mode 100644
index 0000000..e90e520
--- /dev/null
+++ b/tests/integration/j-59/lib/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>j-59-ejb-lib</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-integration-j-59-ejb-lib</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/LocalBeanWithRemoteInterface.java b/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/LocalBeanWithRemoteInterface.java
new file mode 100644
index 0000000..086976a
--- /dev/null
+++ b/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/LocalBeanWithRemoteInterface.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.ejb.lib;
+
+import javax.ejb.LocalBean;
+import javax.ejb.Remote;
+import javax.ejb.Stateless;
+
+/**
+ * Local stateless session bean implementing a remote interface.
+ * Part of CDI extension lookup issue reproducer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+@LocalBean
+@Remote(MyRemoteInterface.class)
+public class LocalBeanWithRemoteInterface {
+
+ /**
+ * Simple getter to be invoked from a CDI backed JAX-RS resource.
+ *
+ * @return Josh string literal.
+ */
+ public String getName() {
+ return "Josh";
+ }
+}
diff --git a/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/MyRemoteInterface.java b/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/MyRemoteInterface.java
new file mode 100644
index 0000000..ff53484
--- /dev/null
+++ b/tests/integration/j-59/lib/src/main/java/org/glassfish/jersey/tests/integration/j59/ejb/lib/MyRemoteInterface.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.ejb.lib;
+
+/**
+ * Marker interface for remote beans. Part of CDI extension lookup issue reproducer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface MyRemoteInterface {
+}
diff --git a/tests/integration/j-59/pom.xml b/tests/integration/j-59/pom.xml
new file mode 100644
index 0000000..2512403
--- /dev/null
+++ b/tests/integration/j-59/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>j-59</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration-j-59</name>
+
+ <description>
+ J-59 Reproducer: CDI extension lookup in multi-module app to Jersey 2.
+ </description>
+
+ <modules>
+ <module>ear</module>
+ <module>lib</module>
+ <module>war</module>
+ </modules>
+</project>
diff --git a/tests/integration/j-59/war/pom.xml b/tests/integration/j-59/war/pom.xml
new file mode 100644
index 0000000..1783544
--- /dev/null
+++ b/tests/integration/j-59/war/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>j-59-cdi-war</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-j-59-cdi-war</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>j-59-ejb-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/CdiBackedResource.java b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/CdiBackedResource.java
new file mode 100644
index 0000000..f3483dd
--- /dev/null
+++ b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/CdiBackedResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.cdi.web;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+import javax.jws.WebResult;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.tests.integration.j59.ejb.lib.LocalBeanWithRemoteInterface;
+
+/**
+ * Part of CDI extension lookup issue reproducer.
+ * This bean will CDI-inject a local EJB bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("name")
+@RequestScoped
+public class CdiBackedResource implements ResourceMarkerInterface {
+
+ @Inject
+ private LocalBeanWithRemoteInterface localBean;
+
+ @GET
+ @Path("hello")
+ @Produces(MediaType.TEXT_PLAIN)
+ @WebResult(name = "hello")
+ public String sayHello() {
+ return "Hello " + localBean.getName();
+ }
+}
diff --git a/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/JaxRsConfiguration.java b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/JaxRsConfiguration.java
new file mode 100644
index 0000000..976125a
--- /dev/null
+++ b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/JaxRsConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.cdi.web;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * CDI extension lookup issue reproducer application configuration.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("resources")
+public class JaxRsConfiguration extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(CdiBackedResource.class);
+ }};
+ }
+}
diff --git a/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/ResourceMarkerInterface.java b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/ResourceMarkerInterface.java
new file mode 100644
index 0000000..f1548c6
--- /dev/null
+++ b/tests/integration/j-59/war/src/main/java/org/glassfish/jersey/tests/integration/j59/cdi/web/ResourceMarkerInterface.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.cdi.web;
+
+/**
+ * Marker interface for CDI backed JAX-RS bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public interface ResourceMarkerInterface {
+}
diff --git a/tests/integration/j-59/war/src/main/webapp/WEB-INF/beans.xml b/tests/integration/j-59/war/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..6d5c2c1
--- /dev/null
+++ b/tests/integration/j-59/war/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
diff --git a/tests/integration/j-59/war/src/main/webapp/index.jsp b/tests/integration/j-59/war/src/main/webapp/index.jsp
new file mode 100644
index 0000000..a59a2a4
--- /dev/null
+++ b/tests/integration/j-59/war/src/main/webapp/index.jsp
@@ -0,0 +1,29 @@
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+
+ Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>CDI Extension Lookup Issue Reproducer</title>
+ </head>
+ <body>
+ Visit <a href="resources/name/hello">resources/name/hello</a>
+ </body>
+</html>
diff --git a/tests/integration/j-59/war/src/test/java/org/glassfish/jersey/tests/integration/j59/cdi/web/NameBeanTest.java b/tests/integration/j-59/war/src/test/java/org/glassfish/jersey/tests/integration/j59/cdi/web/NameBeanTest.java
new file mode 100644
index 0000000..26870a9
--- /dev/null
+++ b/tests/integration/j-59/war/src/test/java/org/glassfish/jersey/tests/integration/j59/cdi/web/NameBeanTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.j59.cdi.web;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test for CDI extension lookup issue. Should the extension lookup have failed,
+ * we would not get the correct response here.
+ * <p/>
+ * Run with:
+ * <pre>
+ * mvn clean package
+ * $AS_HOME/bin/asadmin deploy ../ejb-jax-rs-ear1/target/ejb-jax-rs-ear1
+ * mvn -DskipTests=false test</pre>
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class NameBeanTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsConfiguration();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("j-59-cdi-war").path("resources").build();
+ }
+
+ @Test
+ public void testCdiResource() {
+ final Response r = target().path("name").path("hello").request().get();
+ final String content = r.readEntity(String.class);
+ assertThat(r.getStatus(), is(200));
+ assertThat(content, equalTo("Hello Josh"));
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/pom.xml b/tests/integration/jaxrs-component-inject/pom.xml
new file mode 100644
index 0000000..9a392ab
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jaxrs-component-inject</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-component-inject</name>
+
+ <description>Jersey Jaxrs Component Inject</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/PrintingErrorHandler.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/PrintingErrorHandler.java
new file mode 100644
index 0000000..a8769f3
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/PrintingErrorHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Exception mapper printing the {@link Status#NOT_ACCEPTABLE} error.
+ */
+@Provider
+public class PrintingErrorHandler implements ExceptionMapper<Throwable> {
+
+ @Override
+ public Response toResponse(Throwable throwable) {
+ throwable.printStackTrace();
+
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(result);
+ throwable.printStackTrace(printWriter);
+ return Response.status(Status.NOT_ACCEPTABLE).entity(result.toString())
+ .build();
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/Resource.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/Resource.java
new file mode 100644
index 0000000..6c2a965
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/Resource.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+
+/**
+ * Resource with {@link Context} injection points.
+ */
+@Path("resource")
+public class Resource {
+
+ @Context
+ Application application;
+ @Context
+ UriInfo info;
+ @Context
+ Request request;
+ @Context
+ HttpHeaders headers;
+ @Context
+ SecurityContext security;
+ @Context
+ Providers providers;
+ @Context
+ ResourceContext resources;
+ @Context
+ Configuration configration;
+
+ @POST
+ @Path("echo")
+ public String returnGivenString(String string) {
+ return string;
+ }
+
+ @POST
+ @Path("reader")
+ public String reader(StringBean bean) {
+ return bean.get();
+ }
+
+ @POST
+ @Path("writer")
+ public StringBean writer(String entity) {
+ return new StringBean(entity);
+ }
+
+ @GET
+ @Path("instance")
+ public String instance() {
+ return StringBeanEntityProviderWithInjectables.computeMask(application,
+ info, request, headers, security, providers, resources,
+ configration);
+ }
+
+ @GET
+ @Path("method")
+ public String method(@Context Application application,
+ @Context UriInfo info, @Context Request request,
+ @Context HttpHeaders headers, @Context SecurityContext security,
+ @Context Providers providers, @Context ResourceContext resources) {
+ return StringBeanEntityProviderWithInjectables.computeMask(application,
+ info, request, headers, security, providers, resources,
+ configration);
+ }
+
+ @GET
+ @Path("application")
+ public String application(@Context Application application) {
+ Set<Object> singletons = application.getSingletons();
+ SingletonWithInjectables singleton = (SingletonWithInjectables) singletons
+ .iterator().next();
+ return singleton.getInjectedContextValues();
+ }
+
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/SingletonWithInjectables.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/SingletonWithInjectables.java
new file mode 100644
index 0000000..22ca84a
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/SingletonWithInjectables.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+/**
+ * Holder for application configuration.
+ */
+public class SingletonWithInjectables {
+
+ private TSAppConfig config;
+
+ public SingletonWithInjectables(TSAppConfig config) {
+ this.config = config;
+ }
+
+ public String getInjectedContextValues() {
+ return config.getInjectedContextValues();
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBean.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBean.java
new file mode 100644
index 0000000..40bd98d
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBean.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+/**
+ * This is the object which standard implementation does not have a provider
+ * for, even though its some simple String holder. It can also be used as mutable
+ * string.
+ */
+public class StringBean {
+ private String header;
+
+ public StringBean(String header) {
+ this.header = header;
+ }
+
+ public String get() {
+ return header;
+ }
+
+ public void set(String header) {
+ this.header = header;
+ }
+
+ @Override
+ public String toString() {
+ return "StringBean. To get a value, use rather #get() method.";
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProvider.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProvider.java
new file mode 100644
index 0000000..b8520ab
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Provider for JAX-RS types {@link MessageBodyReader} and {@link MessageBodyWriter}.
+ */
+@Provider
+public class StringBeanEntityProvider implements MessageBodyReader<StringBean>, MessageBodyWriter<StringBean> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return StringBean.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(StringBean t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return t.get().length();
+ }
+
+ @Override
+ public void writeTo(StringBean t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ entityStream.write(t.get().getBytes());
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return isWriteable(type, genericType, annotations, mediaType);
+ }
+
+ @Override
+ public StringBean readFrom(Class<StringBean> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ return null;
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProviderWithInjectables.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProviderWithInjectables.java
new file mode 100644
index 0000000..9b8506f
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/StringBeanEntityProviderWithInjectables.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+/**
+ * Provider with {@link Context} injection points.
+ */
+@Provider
+public class StringBeanEntityProviderWithInjectables extends StringBeanEntityProvider {
+
+ @Context
+ Application application;
+ @Context
+ UriInfo info;
+ @Context
+ Request request;
+ @Context
+ HttpHeaders headers;
+ @Context
+ SecurityContext security;
+ @Context
+ Providers providers;
+ @Context
+ ResourceContext resources;
+ @Context
+ Configuration configuration;
+
+ /**
+ * Chosen decimal as a representation to be more human readable
+ */
+ public static String computeMask(Application application, UriInfo info,
+ Request request, HttpHeaders headers, SecurityContext security,
+ Providers providers, ResourceContext resources,
+ Configuration configuration) {
+ int mask = 1;
+ mask = 10 * mask + (application == null ? 0 : 1);
+ mask = 10 * mask + (info == null ? 0 : 1);
+ mask = 10 * mask + (request == null ? 0 : 1);
+ mask = 10 * mask + (headers == null ? 0 : 1);
+ mask = 10 * mask + (security == null ? 0 : 1);
+ mask = 10 * mask + (providers == null ? 0 : 1);
+ mask = 10 * mask + (resources == null ? 0 : 1);
+ mask = 10 * mask + (configuration == null ? 0 : 1);
+ return String.valueOf(mask);
+ }
+
+ /**
+ * Here, the bitwise operation with mask variable would be more efficient,
+ * but less human readable when sending over the link as a binary number.
+ * Hence, sMask is supposed to be decimal number created by writeTo method.
+ * <p>
+ * If something has not been injected, and thus not written by writeTo, this
+ * static method parses what it was not injected.
+ */
+ public static String notInjected(String sMask) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i != sMask.length(); i++) {
+ sb.append(notInjected(sMask, i));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Here, the bitwise operation with mask variable would be more efficient,
+ * but less human readable when sending over the link as a binary number.
+ * Hence, sMask is supposed to be decimal number created by writeTo method.
+ * <p>
+ * If something has not been injected, and thus not written by writeTo, this
+ * static method parses what it was not injected.
+ */
+ public static final String notInjected(String sMask, int index) {
+ String[] labels = {
+ "Application,", "UriInfo,", "Request,",
+ "HttpHeaders,", "SecurityContext,", "Providers,",
+ "ResourceContext", "Configuration"
+ };
+ String label = "";
+ if (sMask.charAt(index) == '0') {
+ label = labels[index - 1];
+ }
+ return label;
+ }
+
+ @Override
+ public long getSize(StringBean t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return 9;
+ }
+
+ @Override
+ public void writeTo(StringBean t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ entityStream.write(computeMask(application, info, request, headers,
+ security, providers, resources, configuration).getBytes());
+ }
+
+ @Override
+ public StringBean readFrom(Class<StringBean> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ return new StringBean(computeMask(application, info, request, headers,
+ security, providers, resources, configuration));
+ }
+
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/TSAppConfig.java b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/TSAppConfig.java
new file mode 100644
index 0000000..04101c2
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/java/org/glassfish/jersey/tests/jaxrs/inject/TSAppConfig.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+
+/**
+ * Application Configuration with {@link Context} injection points.
+ */
+public class TSAppConfig extends Application {
+
+ @Context
+ UriInfo info;
+ @Context
+ Request request;
+ @Context
+ HttpHeaders headers;
+ @Context
+ SecurityContext security;
+ @Context
+ Providers providers;
+ @Context
+ ResourceContext resources;
+
+ public java.util.Set<java.lang.Class<?>> getClasses() {
+ Set<Class<?>> resources = new HashSet<>();
+ resources.add(Resource.class);
+ resources.add(StringBeanEntityProviderWithInjectables.class);
+ resources.add(PrintingErrorHandler.class);
+ return resources;
+ }
+
+ @Override
+ public Set<Object> getSingletons() {
+ Object single = new SingletonWithInjectables(this);
+ return Collections.singleton(single);
+ }
+
+ public String getInjectedContextValues() {
+ return StringBeanEntityProviderWithInjectables.computeMask(
+ /*
+ * Spec: 9.2.1 Application Note that this cannot be injected into the Application subclass itself since this would
+ * create a circular dependency.
+ * */
+ this, info, request, headers, security, providers, resources,
+ // Configuration injection N/A on Application
+ ClientBuilder.newClient().getConfiguration());
+ }
+}
diff --git a/tests/integration/jaxrs-component-inject/src/main/webapp/WEB-INF/web.xml b/tests/integration/jaxrs-component-inject/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5c07843
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>CTSJAXRSContextServer</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.jaxrs.inject.TSAppConfig</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>CTSJAXRSContextServer</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+</web-app>
diff --git a/tests/integration/jaxrs-component-inject/src/test/java/org/glassfish/jersey/tests/jaxrs/inject/ApplicationInjectITCase.java b/tests/integration/jaxrs-component-inject/src/test/java/org/glassfish/jersey/tests/jaxrs/inject/ApplicationInjectITCase.java
new file mode 100644
index 0000000..50c1ff8
--- /dev/null
+++ b/tests/integration/jaxrs-component-inject/src/test/java/org/glassfish/jersey/tests/jaxrs/inject/ApplicationInjectITCase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.jaxrs.inject;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link javax.ws.rs.core.Context} injection into JAX-RS components Provider, Resource, Application.
+ *
+ * @author Petr Bouda
+ */
+public class ApplicationInjectITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInstance() throws Exception {
+ WebTarget t = target();
+ t.register(LoggingFeature.class);
+ Response r = t.path("/resource/instance").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("111111111", r.readEntity(String.class));
+ }
+
+ @Test
+ public void testMethod() throws Exception {
+ WebTarget t = target();
+ t.register(LoggingFeature.class);
+ Response r = t.path("/resource/method").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("111111111", r.readEntity(String.class));
+ }
+ @Test
+ public void testApplication() throws Exception {
+ WebTarget t = target();
+ t.register(LoggingFeature.class);
+ Response r = t.path("/resource/application").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("111111111", r.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/jersey-1107/pom.xml b/tests/integration/jersey-1107/pom.xml
new file mode 100644
index 0000000..d2ea930
--- /dev/null
+++ b/tests/integration/jersey-1107/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-1107</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1107</name>
+
+ <description>Servlet integration test - JERSEY-1107 - Thread gets stucked if no MessageBodyWriter is found in ApplicationHandler#writeResponse</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-1107/src/main/java/org/glassfish/jersey/tests/integration/jersey1107/Jersey1107.java b/tests/integration/jersey-1107/src/main/java/org/glassfish/jersey/tests/integration/jersey1107/Jersey1107.java
new file mode 100644
index 0000000..7073d75
--- /dev/null
+++ b/tests/integration/jersey-1107/src/main/java/org/glassfish/jersey/tests/integration/jersey1107/Jersey1107.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1107;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Michal Gajdos
+ */
+public class Jersey1107 extends Application {
+
+ /**
+ * This MessageBodyWriter does not support the "exception/nullpointerexception" media type required by the
+ * {@code Resource#getNpe()} method which should result in an empty {@code MessageBodyWriter} and therefore
+ * an NPE in {@code ApplicationHandler}.
+ *
+ * @see org.glassfish.jersey.tests.integration.jersey1107.Jersey1107.Resource#getNpe()
+ */
+ @Provider
+ @Produces({"exception/ioexception", "exception/webapplicationexception"})
+ public static class ExceptionThrower implements MessageBodyWriter<Exception> {
+
+ @Override
+ public boolean isWriteable(
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return IOException.class.isAssignableFrom(type) || RuntimeException.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(
+ Exception t,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(
+ Exception e,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ // Cannot write anything into the entityStream to ensure the ContainerResponseWriter#writeResponseStatusAndHeaders
+ // in ApplicationHandler#writeResponse is not invoked.
+
+ // Simply throw the given exception.
+ if (e instanceof IOException) {
+ throw (IOException) e;
+ } else {
+ throw (RuntimeException) e;
+ }
+ }
+
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ @Path("/ioe")
+ @Produces("exception/ioexception")
+ public IOException getIoe() {
+ return new IOException();
+ }
+
+ @GET
+ @Path("/wae")
+ @Produces("exception/webapplicationexception")
+ public WebApplicationException getWae() {
+ return new WebApplicationException();
+ }
+
+ @GET
+ @Path("/npe")
+ @Produces("exception/nullpointerexception")
+ public NullPointerException getNpe() {
+ return new NullPointerException("This message should never get to the client!");
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {{
+ add(Resource.class);
+ add(ExceptionThrower.class);
+ }};
+ }
+
+}
diff --git a/tests/integration/jersey-1107/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1107/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5c144f8
--- /dev/null
+++ b/tests/integration/jersey-1107/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1107.Jersey1107</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/tests/integration/jersey-1107/src/test/java/org/glassfish/jersey/tests/integration/jersey1107/ApplicationHandlerITCase.java b/tests/integration/jersey-1107/src/test/java/org/glassfish/jersey/tests/integration/jersey1107/ApplicationHandlerITCase.java
new file mode 100644
index 0000000..11cb216
--- /dev/null
+++ b/tests/integration/jersey-1107/src/test/java/org/glassfish/jersey/tests/integration/jersey1107/ApplicationHandlerITCase.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1107;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for JERSEY-1107: Thread gets stuck if no MessageBodyWriter is found in ApplicationHandler#writeResponse.
+ * <p/>
+ * If an exception (e.g. NPE caused by non-existent MessageBodyWriter) is thrown in ApplicationHandler#writeResponse before
+ * headers and response status are written by ContainerResponseWriter#writeResponseStatusAndHeaders then the
+ * ContainerResponseWriter#commit in the finally clause will stuck the thread.
+ * <p/>
+ * The purpose of the tests below is to show that a response is returned from the server and none of the threads gets stuck.
+ *
+ * @author Michal Gajdos
+ */
+public class ApplicationHandlerITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig().registerInstances(new Jersey1107());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Checks if a thread gets stuck when an {@code IOException} is thrown from the {@code
+ * MessageBodyWriter#writeTo}.
+ */
+ @Test
+ public void testIOExceptionInWriteResponseMethod() throws Exception {
+ _testExceptionInWriteResponseMethod("ioe", "exception/ioexception", Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Checks if a thread gets stuck when an {@code WebApplicationException} is thrown from the {@code
+ * MessageBodyWriter#writeTo}.
+ */
+ @Test
+ public void testWebApplicationExceptionInWriteResponseMethod() throws Exception {
+ _testExceptionInWriteResponseMethod("wae", "exception/webapplicationexception", Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Checks if a thread gets stuck when no {@code MessageBodyWriter} is found and therefore an {@code NPE} is thrown
+ * when trying to invoke {@code MessageBodyWriter#writeTo} on an empty object.
+ */
+ @Test
+ public void testNullPointerExceptionInWriteResponseMethod() throws Exception {
+ _testExceptionInWriteResponseMethod("npe", "exception/nullpointerexception", Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Creates a request to the server (with the whole process time set to the maximum of 5 seconds) for the given {@code path}
+ * and {@code mediaType} that should result in the {@code expectedResponse}.
+ */
+ private void _testExceptionInWriteResponseMethod(final String path, final String mediaType,
+ final Response.Status expectedResponse) throws Exception {
+ // Executor.
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ final Future<Response> responseFuture = executor.submit(new Callable<Response>() {
+
+ @Override
+ public Response call() throws Exception {
+ return target().path(path).request(mediaType).get();
+ }
+
+ });
+
+ executor.shutdown();
+ final boolean inTime = executor.awaitTermination(5000, TimeUnit.MILLISECONDS);
+
+ // Asserts.
+ assertTrue(inTime);
+
+ // Response.
+ final Response response = responseFuture.get();
+ assertEquals(expectedResponse.getStatusCode(), response.getStatusInfo().getStatusCode());
+ }
+
+}
diff --git a/tests/integration/jersey-1223/pom.xml b/tests/integration/jersey-1223/pom.xml
new file mode 100644
index 0000000..4bc9d10
--- /dev/null
+++ b/tests/integration/jersey-1223/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jersey-1223</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1223</name>
+ <url>http://maven.apache.org</url>
+
+ <description>
+ Servlet integration test - JERSEY-1223 - "500 Internal Server Error" for POST request with garbage instead of
+ "Content-Type"
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-1223/src/main/java/org/glassfish/jersey/tests/integration/jersey1223/Jersey1223.java b/tests/integration/jersey-1223/src/main/java/org/glassfish/jersey/tests/integration/jersey1223/Jersey1223.java
new file mode 100644
index 0000000..60fcd3c
--- /dev/null
+++ b/tests/integration/jersey-1223/src/main/java/org/glassfish/jersey/tests/integration/jersey1223/Jersey1223.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1223;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+public class Jersey1223 extends Application {
+
+ @Path(value = "/ContentType")
+ public static class ContentTypeResource {
+
+ @POST
+ @Produces(value = "text/plain")
+ @SuppressWarnings({"UnusedParameters", "JavaDoc"})
+ public void postTest(final String str) {
+ // Ignore to generate response 204 - NoContent.
+ }
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.<Class<?>>singleton(ContentTypeResource.class);
+ }
+}
diff --git a/tests/integration/jersey-1223/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1223/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1634824
--- /dev/null
+++ b/tests/integration/jersey-1223/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1223.Jersey1223</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
+
+
diff --git a/tests/integration/jersey-1223/src/test/java/org/glassfish/jersey/tests/integration/jersey1223/ApplicationHandlerITCase.java b/tests/integration/jersey-1223/src/test/java/org/glassfish/jersey/tests/integration/jersey1223/ApplicationHandlerITCase.java
new file mode 100644
index 0000000..6ea3471
--- /dev/null
+++ b/tests/integration/jersey-1223/src/test/java/org/glassfish/jersey/tests/integration/jersey1223/ApplicationHandlerITCase.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1223;
+
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests JERSEY issue 1223.
+ *
+ * @author Michal Gajdos
+ */
+public class ApplicationHandlerITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(Jersey1223.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInvalidContentTypeHeader() throws Exception {
+ final URL url = new URL(getBaseUri().toString() + "ContentType");
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.setRequestProperty("Content-Type", "application/json, app/json");
+
+ connection.setDoOutput(true);
+ connection.connect();
+
+ final OutputStream outputStream = connection.getOutputStream();
+ outputStream.write("HelloWorld!".getBytes());
+ outputStream.write('\n');
+ outputStream.flush();
+
+ assertEquals(400, connection.getResponseCode());
+ }
+}
diff --git a/tests/integration/jersey-1604/pom.xml b/tests/integration/jersey-1604/pom.xml
new file mode 100644
index 0000000..c7ec7b2
--- /dev/null
+++ b/tests/integration/jersey-1604/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jersey-1604</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1604</name>
+ <url>http://maven.apache.org</url>
+
+ <description>Servlet integration test - JERSEY-1604 - IOException "connection closed" happens on calling delete without parameters</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-1604/src/main/java/org/glassfish/jersey/tests/integration/jersey1604/Jersey1604.java b/tests/integration/jersey-1604/src/main/java/org/glassfish/jersey/tests/integration/jersey1604/Jersey1604.java
new file mode 100644
index 0000000..d4a2bbd
--- /dev/null
+++ b/tests/integration/jersey-1604/src/main/java/org/glassfish/jersey/tests/integration/jersey1604/Jersey1604.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1604;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Application class with test resource that sets {@code Connection} header to {@code close}.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1604 extends Application {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.<Class<?>>singleton(TestResource.class);
+ }
+
+ @Path("/")
+ public static class TestResource {
+
+ @DELETE
+ public Response delete() {
+ return Response
+ .ok()
+ .type(MediaType.TEXT_PLAIN_TYPE)
+ .header("Connection", "close")
+ .build();
+ }
+ }
+}
diff --git a/tests/integration/jersey-1604/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1604/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..91aaa79
--- /dev/null
+++ b/tests/integration/jersey-1604/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1604.Jersey1604</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
+
+
diff --git a/tests/integration/jersey-1604/src/test/java/org/glassfish/jersey/tests/integration/jersey1604/ConnectionCloseITCase.java b/tests/integration/jersey-1604/src/test/java/org/glassfish/jersey/tests/integration/jersey1604/ConnectionCloseITCase.java
new file mode 100644
index 0000000..067cbff
--- /dev/null
+++ b/tests/integration/jersey-1604/src/test/java/org/glassfish/jersey/tests/integration/jersey1604/ConnectionCloseITCase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1604;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Tests JERSEY issue 1604.
+ *
+ * @author Michal Gajdos
+ */
+public class ConnectionCloseITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(Jersey1604.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(new ApacheConnectorProvider());
+ }
+
+ @Test
+ public void testConnectionClose() throws Exception {
+ final Response response = target().request().header("Connection", "close").delete();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.hasEntity(), is(false));
+ }
+}
diff --git a/tests/integration/jersey-1667/pom.xml b/tests/integration/jersey-1667/pom.xml
new file mode 100644
index 0000000..1e0243f
--- /dev/null
+++ b/tests/integration/jersey-1667/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-1667</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1667</name>
+
+ <description>Servlet integration test - JERSEY-1667 - Incorrect handling of file upload errors when temp files cannot be written</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Issue1667Resource.java b/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Issue1667Resource.java
new file mode 100644
index 0000000..46ba64c
--- /dev/null
+++ b/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Issue1667Resource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1667;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+/**
+ * Test resource.
+ *
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Issue1667Resource {
+
+ @POST
+ @Path("part-file-name")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public String post(
+ @FormDataParam("part") String s,
+ @FormDataParam("part") FormDataContentDisposition d) {
+ return s + ":" + d.getFileName();
+ }
+}
diff --git a/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667.java b/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667.java
new file mode 100644
index 0000000..026623c
--- /dev/null
+++ b/tests/integration/jersey-1667/src/main/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1667;
+
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.media.multipart.MultiPartProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-1667 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1667 extends ResourceConfig {
+
+ public Jersey1667() {
+ register(Issue1667Resource.class);
+ register(MultiPartFeature.class);
+
+ register(new MultiPartProperties().bufferThreshold(8192).tempDir("/non-existent-directory").resolver());
+ }
+}
diff --git a/tests/integration/jersey-1667/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1667/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5897705
--- /dev/null
+++ b/tests/integration/jersey-1667/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey1667Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1667.Jersey1667</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey1667Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-1667/src/test/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667ITCase.java b/tests/integration/jersey-1667/src/test/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667ITCase.java
new file mode 100644
index 0000000..4e9523e
--- /dev/null
+++ b/tests/integration/jersey-1667/src/test/java/org/glassfish/jersey/tests/integration/jersey1667/Jersey1667ITCase.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1667;
+
+import java.util.Arrays;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2160.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1667ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(MultiPartFeature.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Reproducer method for JERSEY-1667.
+ */
+ @Test
+ public void testJersey1667Fix() {
+ final WebTarget target = target().path("part-file-name");
+
+ char[] chars = new char[10 * 1024];
+ Arrays.fill(chars, 'a');
+ final String body = new String(chars);
+
+ final FormDataMultiPart multiPart = new FormDataMultiPart();
+ final FormDataBodyPart bodyPart = new FormDataBodyPart(FormDataContentDisposition.name("part").fileName("file").build(),
+ body);
+ multiPart.bodyPart(bodyPart);
+
+ final Response response = target.request().post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE));
+
+ assertThat(response.getStatus(), equalTo(500));
+ }
+}
diff --git a/tests/integration/jersey-1829/pom.xml b/tests/integration/jersey-1829/pom.xml
new file mode 100644
index 0000000..c4f1599
--- /dev/null
+++ b/tests/integration/jersey-1829/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jersey-1829</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1829</name>
+ <url>http://maven.apache.org</url>
+
+
+ <description>Servlet integration test - JERSEY-1829 - Custom reason phrase in response status does not work</description>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-1829/src/main/java/org/glassfish/jersey/tests/integration/jersey1829/Jersey1829.java b/tests/integration/jersey-1829/src/main/java/org/glassfish/jersey/tests/integration/jersey1829/Jersey1829.java
new file mode 100644
index 0000000..e2398f2
--- /dev/null
+++ b/tests/integration/jersey-1829/src/main/java/org/glassfish/jersey/tests/integration/jersey1829/Jersey1829.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1829;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+/**
+ * Application class with test resource that returns custom status reason phrase.
+ *
+ * @author Miroslav Fuksa
+ */
+public class Jersey1829 extends Application {
+
+ public static final String REASON_PHRASE = "my-phrase";
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.<Class<?>>singleton(TestResource.class);
+ }
+
+ @Path("resource")
+ public static class TestResource {
+
+ @GET
+ @Path("428")
+ public Response get() {
+ return Response.status(new Custom428Type()).build();
+ }
+
+ @GET
+ @Path("428-entity")
+ public Response getWithEntity() {
+ return Response.status(new Custom428Type()).entity("entity").build();
+ }
+ }
+
+ public static class Custom428Type implements Response.StatusType {
+
+ @Override
+ public int getStatusCode() {
+ return 428;
+ }
+
+ @Override
+ public String getReasonPhrase() {
+ return REASON_PHRASE;
+ }
+
+ @Override
+ public Response.Status.Family getFamily() {
+ return Response.Status.Family.CLIENT_ERROR;
+ }
+ }
+
+}
diff --git a/tests/integration/jersey-1829/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1829/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5e51210
--- /dev/null
+++ b/tests/integration/jersey-1829/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1829.Jersey1829</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
+
+
diff --git a/tests/integration/jersey-1829/src/test/java/org/glassfish/jersey/tests/integration/jersey1829/ApplicationHandlerITCase.java b/tests/integration/jersey-1829/src/test/java/org/glassfish/jersey/tests/integration/jersey1829/ApplicationHandlerITCase.java
new file mode 100644
index 0000000..11f81af
--- /dev/null
+++ b/tests/integration/jersey-1829/src/test/java/org/glassfish/jersey/tests/integration/jersey1829/ApplicationHandlerITCase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1829;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests JERSEY issue 1744. Custom status reason phrase returned from the resource method was not propagated out of the
+ * servlet container.
+ *
+ * @author Miroslav Fuksa
+ */
+public class ApplicationHandlerITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(Jersey1829.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testCustomResponse428() {
+ final Response response = target().path("resource/428").request().get();
+ Assert.assertEquals(428, response.getStatusInfo().getStatusCode());
+ Assert.assertEquals("my-phrase", response.getStatusInfo().getReasonPhrase());
+ }
+
+ @Test
+ public void testCustomResponse428WithEntity() {
+ final Response response = target().path("resource/428-entity").request().get();
+ Assert.assertEquals(428, response.getStatusInfo().getStatusCode());
+ Assert.assertEquals("my-phrase", response.getStatusInfo().getReasonPhrase());
+
+ }
+}
diff --git a/tests/integration/jersey-1883/pom.xml b/tests/integration/jersey-1883/pom.xml
new file mode 100644
index 0000000..c9c8fc0
--- /dev/null
+++ b/tests/integration/jersey-1883/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-1883</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1883</name>
+
+ <description>Servlet integration test - JERSEY-1883 - @PostConstruct method called twice on @Singleton</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/Life.java b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/Life.java
new file mode 100644
index 0000000..37effa2
--- /dev/null
+++ b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/Life.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1883;
+
+import javax.annotation.PostConstruct;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application mixed with resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/rest3")
+@Path("/life")
+public class Life extends Application {
+
+ private static int postConstructCount = 0;
+
+ @PostConstruct
+ public void post_construct() {
+ postConstructCount++;
+ }
+
+ @GET
+ public String greet() {
+ return "hi #" + postConstructCount;
+ }
+}
diff --git a/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/MyApplication.java b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/MyApplication.java
new file mode 100644
index 0000000..764a7b6
--- /dev/null
+++ b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/MyApplication.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1883;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Explicitly register {@code @Singleton} resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/rest1")
+public class MyApplication extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.singleton(NoLife.class);
+ }
+}
diff --git a/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/NoLife.java b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/NoLife.java
new file mode 100644
index 0000000..9a82223
--- /dev/null
+++ b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/NoLife.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1883;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+/**
+ * Explicitly registered singleton resource by {@link MyApplication}.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Singleton
+@Path("/no-life")
+public class NoLife extends Application {
+
+ private static int postConstructCount = 0;
+
+ @PostConstruct
+ public void post_construct() {
+ postConstructCount++;
+ }
+
+ @GET
+ public String greet() {
+ return "ciao #" + postConstructCount;
+ }
+}
diff --git a/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/SingletonLife.java b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/SingletonLife.java
new file mode 100644
index 0000000..26ae80b
--- /dev/null
+++ b/tests/integration/jersey-1883/src/main/java/org/glassfish/jersey/tests/integration/jersey1883/SingletonLife.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1883;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Singleton;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application mixed with resource - singleton class.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Singleton
+@ApplicationPath("/rest2")
+@Path("/singleton-life")
+public class SingletonLife extends Application {
+
+ private static int postConstructCount = 0;
+
+ @PostConstruct
+ public void post_construct() {
+ postConstructCount++;
+ }
+
+ @GET
+ public String greet() {
+ return "hello #" + postConstructCount;
+ }
+}
diff --git a/tests/integration/jersey-1883/src/test/java/org/glassfish/jersey/tests/integration/jersey1883/Jersey1883ITCase.java b/tests/integration/jersey-1883/src/test/java/org/glassfish/jersey/tests/integration/jersey1883/Jersey1883ITCase.java
new file mode 100644
index 0000000..b2fb307
--- /dev/null
+++ b/tests/integration/jersey-1883/src/test/java/org/glassfish/jersey/tests/integration/jersey1883/Jersey1883ITCase.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1883;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Jersey1883ITCase extends JerseyTest {
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testGetRestNoLife() throws Exception {
+ Response response = target("rest1").path("no-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("ciao #1"));
+
+ response = target("rest1").path("no-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("ciao #1"));
+
+ response = target("rest1").path("no-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("ciao #1"));
+
+ response = target("rest1").path("no-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("ciao #1"));
+ }
+
+ @Test
+ public void testGetRestSingletonLife() throws Exception {
+ Response response = target("rest2").path("singleton-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hello #1"));
+
+ response = target("rest2").path("singleton-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hello #1"));
+
+ response = target("rest2").path("singleton-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hello #1"));
+
+ response = target("rest2").path("singleton-life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hello #1"));
+ }
+
+ @Test
+ public void testGetRestLife() throws Exception {
+ Response response = target("rest3").path("life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hi #2"));
+
+ response = target("rest3").path("life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hi #3"));
+
+ response = target("rest3").path("life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hi #4"));
+
+ response = target("rest3").path("life").request().get();
+ assertThat(response.readEntity(String.class), equalTo("hi #5"));
+ }
+
+}
diff --git a/tests/integration/jersey-1928/pom.xml b/tests/integration/jersey-1928/pom.xml
new file mode 100644
index 0000000..5bbc778
--- /dev/null
+++ b/tests/integration/jersey-1928/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jersey-1928</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1928</name>
+ <url>http://maven.apache.org</url>
+
+
+ <description>Servlet integration test - JERSEY-1928 - Odd behaviour with empty "path info"</description>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-1928/src/main/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928.java b/tests/integration/jersey-1928/src/main/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928.java
new file mode 100644
index 0000000..dde2159
--- /dev/null
+++ b/tests/integration/jersey-1928/src/main/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1928;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/jersey1928")
+public class Jersey1928 extends Application {
+
+ @Path("/")
+ public static class Resource {
+
+ @GET
+ public String list() {
+ return "list";
+ }
+
+ @GET
+ @Path("{id}")
+ public String get(@PathParam("id") final String id) {
+ return id;
+ }
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.<Class<?>>singleton(Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-1928/src/test/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928ITCase.java b/tests/integration/jersey-1928/src/test/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928ITCase.java
new file mode 100644
index 0000000..8fa797b
--- /dev/null
+++ b/tests/integration/jersey-1928/src/test/java/org/glassfish/jersey/tests/integration/jersey1928/Jersey1928ITCase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1928;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Tests JERSEY issue 1928.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1928ITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testJersey1928List() throws Exception {
+ final Response response = target("jersey1928").request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("list"));
+ }
+
+ @Test
+ public void testJersey1928Id() throws Exception {
+ final Response response = target("jersey1928").path("id").request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("id"));
+ }
+}
diff --git a/tests/integration/jersey-1960/pom.xml b/tests/integration/jersey-1960/pom.xml
new file mode 100644
index 0000000..4de96cb
--- /dev/null
+++ b/tests/integration/jersey-1960/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-1960</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1960</name>
+
+ <description>Servlet integration test - JERSEY-1960 - Servlet artifact injection into singleton providers.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/EchoResource.java b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/EchoResource.java
new file mode 100644
index 0000000..ca3b1a9
--- /dev/null
+++ b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/EchoResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1960;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("echo")
+public class EchoResource {
+
+ @POST
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public String echo(String message) {
+ return message + "." + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960App.java b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960App.java
new file mode 100644
index 0000000..8a87f0b
--- /dev/null
+++ b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960App.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1960;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application for the JERSEY-1960 reproducer test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@ApplicationPath("application_path")
+public class Jersey1960App extends Application {
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Stream.of(EchoResource.class, RequestFilter.class).collect(Collectors.toSet());
+ }
+}
diff --git a/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/RequestFilter.java b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/RequestFilter.java
new file mode 100644
index 0000000..fde6d21
--- /dev/null
+++ b/tests/integration/jersey-1960/src/main/java/org/glassfish/jersey/tests/integration/jersey1960/RequestFilter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1960;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * Filter testing injection support for of servlet artifacts.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@PreMatching
+public class RequestFilter implements ContainerRequestFilter {
+ public static final String REQUEST_NUMBER = "request-number";
+ @Context
+ private HttpServletRequest hsReq;
+ @Context
+ private HttpServletResponse hsResp;
+ @Context
+ private ServletContext sCtx;
+ @Context
+ private ServletConfig sCfg;
+
+ @Override
+ public void filter(final ContainerRequestContext ctx) throws IOException {
+ final StringBuilder sb = new StringBuilder();
+
+ // First, make sure there are no null injections.
+ if (hsReq == null) {
+ sb.append("HttpServletRequest is null.\n");
+ }
+ if (hsResp == null) {
+ sb.append("HttpServletResponse is null.\n");
+ }
+ if (sCtx == null) {
+ sb.append("ServletContext is null.\n");
+ }
+ if (sCfg == null) {
+ sb.append("ServletConfig is null.\n");
+ }
+
+ if (sb.length() > 0) {
+ ctx.abortWith(Response.serverError().entity(sb.toString()).build());
+ }
+
+ // let's also test some method calls
+ int flags = 0;
+
+ if ("/jersey-1960".equals(hsReq.getServletPath())) {
+ flags += 1;
+ }
+ if (!hsResp.isCommitted()) {
+ flags += 10;
+ }
+ if (!sCtx.getServerInfo().isEmpty()) {
+ flags += 100;
+ }
+ if (sCfg.getServletContext() == sCtx) {
+ flags += 1000;
+ }
+ final String header = hsReq.getHeader(REQUEST_NUMBER);
+
+ ctx.setEntityStream(new ByteArrayInputStream(("filtered-" + flags + "-" + header).getBytes(
+ MessageUtils.getCharset(ctx.getMediaType()))));
+ }
+}
diff --git a/tests/integration/jersey-1960/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1960/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..8ba90c2
--- /dev/null
+++ b/tests/integration/jersey-1960/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey1960Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1960.Jersey1960App</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey1960Servlet</servlet-name>
+ <url-pattern>/jersey-1960/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-1960/src/test/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960ITCase.java b/tests/integration/jersey-1960/src/test/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960ITCase.java
new file mode 100644
index 0000000..da03ead
--- /dev/null
+++ b/tests/integration/jersey-1960/src/test/java/org/glassfish/jersey/tests/integration/jersey1960/Jersey1960ITCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1960;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer tests for JERSEY-1960.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class Jersey1960ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey1960App();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Reproducer method for JERSEY-1960.
+ */
+ @Test
+ public void testJersey1960Fix() {
+ for (int i = 0; i < 10; i++) {
+ String response = target().path("jersey-1960/echo").request().header(RequestFilter.REQUEST_NUMBER, i)
+ .post(Entity.text("test"), String.class);
+ // Assert that the request has been filtered and processed by the echo method.
+ assertEquals(new EchoResource().echo("filtered-1111-" + i), response);
+ }
+ }
+}
diff --git a/tests/integration/jersey-1964/pom.xml b/tests/integration/jersey-1964/pom.xml
new file mode 100644
index 0000000..b6615c6
--- /dev/null
+++ b/tests/integration/jersey-1964/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-1964</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-1964</name>
+
+ <description>Servlet integration test - JERSEY-1964 - NPE with Jersey 1 + Jackson 2 JAX-RS JSON provider</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-metainf-services</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Issue1964Resource.java b/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Issue1964Resource.java
new file mode 100644
index 0000000..839fc53
--- /dev/null
+++ b/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Issue1964Resource.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1964;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource.
+ *
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Issue1964Resource {
+
+ public static class JsonStringWrapper {
+
+ private String value;
+
+ public JsonStringWrapper() {
+ }
+
+ public JsonStringWrapper(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ @PUT
+ @Consumes("application/json")
+ @Produces("application/json")
+ public JsonStringWrapper put(final JsonStringWrapper wrapper) {
+ return wrapper;
+ }
+}
diff --git a/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964.java b/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964.java
new file mode 100644
index 0000000..3dd1b6b
--- /dev/null
+++ b/tests/integration/jersey-1964/src/main/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1964;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-1964 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1964 extends ResourceConfig {
+
+ public Jersey1964() {
+ register(Issue1964Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-1964/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-1964/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7736f49
--- /dev/null
+++ b/tests/integration/jersey-1964/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey1964Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey1964.Jersey1964</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey1964Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-1964/src/test/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964ITCase.java b/tests/integration/jersey-1964/src/test/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964ITCase.java
new file mode 100644
index 0000000..8329fd5
--- /dev/null
+++ b/tests/integration/jersey-1964/src/test/java/org/glassfish/jersey/tests/integration/jersey1964/Jersey1964ITCase.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey1964;
+
+import java.net.ConnectException;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Reproducer tests for JERSEY-1964.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey1964ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey1964();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testJackson2JsonPut() throws Exception {
+ final Response response = target().request().put(Entity.json(new Issue1964Resource.JsonStringWrapper("foo")));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(Issue1964Resource.JsonStringWrapper.class).getValue(), equalTo("foo"));
+ }
+
+ @Test(expected = ConnectException.class)
+ public void testJackson2JsonGetInvalidEndpoint() throws Throwable {
+ try {
+ ClientBuilder.newClient()
+ .target("http://localhost:1234")
+ .request()
+ .get();
+
+ fail("End-point shouldn't exist.");
+ } catch (final ProcessingException pe) {
+ throw pe.getCause();
+ }
+ }
+
+ @Test(expected = ConnectException.class)
+ public void testJackson2JsonPutInvalidEndpoint() throws Throwable {
+ try {
+ ClientBuilder.newClient()
+ .target("http://localhost:1234")
+ .request()
+ .put(Entity.json(new Issue1964Resource.JsonStringWrapper("foo")));
+
+ fail("End-point shouldn't exist.");
+ } catch (final ProcessingException pe) {
+ throw pe.getCause();
+ }
+ }
+}
diff --git a/tests/integration/jersey-2031/pom.xml b/tests/integration/jersey-2031/pom.xml
new file mode 100644
index 0000000..7b0eea3
--- /dev/null
+++ b/tests/integration/jersey-2031/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2031</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2031</name>
+
+ <description>Servlet integration test - JERSEY-2031 - jersey 2.1 explicit viewable resolvingClass missed when do a jsp tag</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-jsp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource.java b/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource.java
new file mode 100644
index 0000000..1e9fa59
--- /dev/null
+++ b/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2031;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+
+/**
+ * Test resource.
+ *
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Issue2031Resource {
+
+ private static final Model model;
+ private static final String absolutePath;
+
+ static {
+ absolutePath = "/" + Issue2031Resource.class.getName().replaceAll("\\.", "/").replace('$', '/') + "/index.jsp";
+ model = new Model();
+ }
+
+ @GET
+ @Path("viewable-relative")
+ @Produces("text/html")
+ public Viewable viewableRelative() {
+ return new Viewable("index", model);
+ }
+
+ @GET
+ @Path("viewable-absolute")
+ @Produces("text/html")
+ public Viewable viewableAbsolute() {
+ return new Viewable(absolutePath, model);
+ }
+
+ @GET
+ @Path("template-relative")
+ @Produces("text/html")
+ @Template(name = "index")
+ public Model templateRelative() {
+ return model;
+ }
+
+ @GET
+ @Path("template-absolute")
+ @Produces("text/html")
+ @Template(
+ name = "/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/index.jsp")
+ public Model templateAbsolute() {
+ return model;
+ }
+
+ public static class Model {
+
+ private String index = "index";
+ private String include = "include";
+
+ public String getIndex() {
+ return index;
+ }
+
+ public String getInclude() {
+ return include;
+ }
+ }
+}
diff --git a/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031.java b/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031.java
new file mode 100644
index 0000000..3c673eb
--- /dev/null
+++ b/tests/integration/jersey-2031/src/main/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2031;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
+
+/**
+ * JAX-RS application for the JERSEY-2031 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2031 extends ResourceConfig {
+
+ public Jersey2031() {
+ register(Issue2031Resource.class);
+ register(JspMvcFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2031/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2031/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..18fc4e3
--- /dev/null
+++ b/tests/integration/jersey-2031/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>jersey2031</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2031.Jersey2031</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>jersey2031</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/include.jsp b/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/include.jsp
new file mode 100644
index 0000000..6c914c2
--- /dev/null
+++ b/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/include.jsp
@@ -0,0 +1,22 @@
+<%--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+
+${model.include}
diff --git a/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/index.jsp b/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/index.jsp
new file mode 100644
index 0000000..cbebedb
--- /dev/null
+++ b/tests/integration/jersey-2031/src/main/webapp/org/glassfish/jersey/tests/integration/jersey2031/Issue2031Resource/index.jsp
@@ -0,0 +1,39 @@
+<%--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Book</title>
+ </head>
+ <body>
+
+ ${model.index}
+
+ <rbt:include page="include.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/jersey-2031/src/test/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031ITCase.java b/tests/integration/jersey-2031/src/test/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031ITCase.java
new file mode 100644
index 0000000..594129b
--- /dev/null
+++ b/tests/integration/jersey-2031/src/test/java/org/glassfish/jersey/tests/integration/jersey2031/Jersey2031ITCase.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2031;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2164.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2031ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2031();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testTemplateRelative() throws Exception {
+ _test("template-relative");
+ }
+
+ @Test
+ public void testTemplateAbsolute() throws Exception {
+ _test("template-absolute");
+ }
+
+ @Test
+ public void testViewableRelative() throws Exception {
+ _test("viewable-relative");
+ }
+
+ @Test
+ public void testViewableAbsolute() throws Exception {
+ _test("viewable-absolute");
+ }
+
+ private void _test(final String path) throws Exception {
+ final Response response = target(path).request("text/html").get();
+ final String page = response.readEntity(String.class);
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(page, containsString("index"));
+ assertThat(page, containsString("include"));
+ }
+}
diff --git a/tests/integration/jersey-2136/pom.xml b/tests/integration/jersey-2136/pom.xml
new file mode 100644
index 0000000..5e797da
--- /dev/null
+++ b/tests/integration/jersey-2136/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2136</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2136</name>
+
+ <description>Servlet integration test - JERSEY-2136 - Jersey 2 doesn't work with Google Application Engine</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.appengine</groupId>
+ <artifactId>appengine-api-1.0-sdk</artifactId>
+ <version>${gae.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <!-- TODO: The test was skipped, including the hooked app-engine start && stop. The app-engine process was sometimes
+ left hanging after the end of the build and kept blocking the port. -->
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <!--<plugin>-->
+ <!--<groupId>com.google.appengine</groupId>-->
+ <!--<artifactId>appengine-maven-plugin</artifactId>-->
+ <!--<version>${gae.version}</version>-->
+ <!--<configuration>-->
+
+ <!--<port>${jersey.config.test.container.port}</port>-->
+ <!--<offline>true</offline>-->
+ <!--</configuration>-->
+ <!--<executions>-->
+ <!--<execution>-->
+ <!--<id>start-gae</id>-->
+ <!--<phase>pre-integration-test</phase>-->
+ <!--<goals>-->
+ <!--<goal>devserver_start</goal>-->
+ <!--</goals>-->
+ <!--</execution>-->
+ <!--<execution>-->
+ <!--<id>stop-gae</id>-->
+ <!--<phase>post-integration-test</phase>-->
+ <!--<goals>-->
+ <!--<goal>devserver_stop</goal>-->
+ <!--</goals>-->
+ <!--</execution>-->
+ <!--</executions>-->
+ <!--</plugin>-->
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Issue2136Resource.java b/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Issue2136Resource.java
new file mode 100644
index 0000000..ede5954
--- /dev/null
+++ b/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Issue2136Resource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2136;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * Test resource.
+ *
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Issue2136Resource {
+
+ @GET
+ public String get() {
+ return "Hello, GAE!";
+ }
+}
diff --git a/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136.java b/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136.java
new file mode 100644
index 0000000..b7f604e
--- /dev/null
+++ b/tests/integration/jersey-2136/src/main/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2136;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2136 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2136 extends ResourceConfig {
+
+ public Jersey2136() {
+ register(Issue2136Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-2136/src/main/webapp/WEB-INF/appengine-web.xml b/tests/integration/jersey-2136/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 0000000..fc291a1
--- /dev/null
+++ b/tests/integration/jersey-2136/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
+ <application>jersey2136</application>
+ <version>1</version>
+ <threadsafe>true</threadsafe>
+</appengine-web-app>
diff --git a/tests/integration/jersey-2136/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2136/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2c67157
--- /dev/null
+++ b/tests/integration/jersey-2136/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2136Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2136.Jersey2136</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2136Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2136/src/test/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136ITCase.java b/tests/integration/jersey-2136/src/test/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136ITCase.java
new file mode 100644
index 0000000..418666a
--- /dev/null
+++ b/tests/integration/jersey-2136/src/test/java/org/glassfish/jersey/tests/integration/jersey2136/Jersey2136ITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2136;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2164.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2136ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2136();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ // This test requires app engine to be launched by a maven plugin,
+ // which was causing intermittent problems with hanging app engine process.
+ // After un-ignoring this test, make sure to uncomment the app engine plugin
+ // execution in the project's pom.xml
+ @Ignore
+ @Test
+ public void testGet() throws Exception {
+ final Response response = target().request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("Hello, GAE!"));
+ }
+}
diff --git a/tests/integration/jersey-2137/pom.xml b/tests/integration/jersey-2137/pom.xml
new file mode 100644
index 0000000..d5b48c5
--- /dev/null
+++ b/tests/integration/jersey-2137/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2137</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2137</name>
+
+ <description>Jersey CDI/JTA test web application, JERSEY-2137 reproducer</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/Account.java b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/Account.java
new file mode 100644
index 0000000..1c414b7
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/Account.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2137;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * Entity bean that maintains information on account balance.
+ * This is to help determine if rollback happens or not, when
+ * entity bean is accessed from a transactional CDI beans.
+ * Entity beans have implicit JTA support, so this will
+ * save us some lines of code.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Entity
+public class Account implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ private Long id;
+
+ /**
+ * Get the account id.
+ *
+ * @return account id.
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * Set the account id.
+ *
+ * @param id account id.
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ private long balance;
+
+ /**
+ * Get the value of balance
+ *
+ * @return the value of balance
+ */
+ public long getBalance() {
+ return balance;
+ }
+
+ /**
+ * Set the value of balance
+ *
+ * @param balance new value of balance
+ */
+ public void setBalance(long balance) {
+ this.balance = balance;
+ }
+
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ hash += (id != null ? id.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof Account)) {
+ return false;
+ }
+ Account other = (Account) object;
+ if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "org.glassfish.jersey.tests.integration.jersey2137.Account[ id=" + id + " ]";
+ }
+}
diff --git a/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalNoRollbackResource.java b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalNoRollbackResource.java
new file mode 100644
index 0000000..3ce59b1
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalNoRollbackResource.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2137;
+
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import javax.enterprise.context.RequestScoped;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.transaction.Transactional;
+
+/**
+ * Request scoped transactional CDI bean registered as JAX-RS resource class.
+ * Part of JERSEY-2137 reproducer. {@link javax.ws.rs.WebApplicationException}
+ * thrown in the resource method below should drive the response as specified
+ * in the JAX-RS spec regardless
+ * on the {@link javax.transaction.Transactional#dontRollbackOn()} value.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Transactional(dontRollbackOn = WebApplicationException.class)
+@Path("cdi-transactional-no-rollback")
+public class CdiTransactionalNoRollbackResource {
+
+ @PersistenceContext(unitName = "Jersey2137PU")
+ private EntityManager entityManager;
+
+ @Path("{a}")
+ @PUT
+ public void putBalance(@PathParam("a") long a, String balance) {
+ final Account account = entityManager.find(Account.class, a);
+ if (account == null) {
+ Account newAccount = new Account();
+ newAccount.setId(a);
+ newAccount.setBalance(Long.decode(balance));
+ entityManager.persist(newAccount);
+ throw new WebApplicationException(Response.ok("New accout created.").build());
+ } else {
+ account.setBalance(Long.decode(balance));
+ entityManager.merge(account);
+ throw new WebApplicationException(Response.ok("Balance updated.").build());
+ }
+ }
+}
diff --git a/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalResource.java b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalResource.java
new file mode 100644
index 0000000..0132a91
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/CdiTransactionalResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2137;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import javax.enterprise.context.RequestScoped;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.transaction.Transactional;
+
+/**
+ * Request scoped transactional CDI bean registered as JAX-RS resource class.
+ * Part of JERSEY-2137 reproducer. {@link javax.ws.rs.WebApplicationException}
+ * thrown in the resource method below should drive the response as specified
+ * in the JAX-RS spec.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Transactional
+@Path("cdi-transactional")
+public class CdiTransactionalResource {
+
+ @PersistenceContext(unitName = "Jersey2137PU")
+ private EntityManager entityManager;
+
+ @Path("{a}")
+ @GET
+ public String getBalance(@PathParam("a") long a) {
+ final Account account = entityManager.find(Account.class, a);
+ if (account == null) {
+ throw new WebApplicationException(
+ Response.status(Response.Status.BAD_REQUEST).entity(String.format("Account %d not found", a)).build());
+ } else {
+ return String.format("%d", account.getBalance());
+ }
+ }
+
+ @Path("{a}")
+ @PUT
+ public void putBalance(@PathParam("a") long a, String balance) {
+ final Account account = entityManager.find(Account.class, a);
+ if (account == null) {
+ Account newAccount = new Account();
+ newAccount.setId(a);
+ newAccount.setBalance(Long.decode(balance));
+ entityManager.persist(newAccount);
+ } else {
+ account.setBalance(Long.decode(balance));
+ entityManager.merge(account);
+ }
+ }
+
+ @POST
+ public String transferMoney(@QueryParam("from") long from, @QueryParam("to") long to, String amount) {
+
+ final Account toAccount = entityManager.find(Account.class, to);
+
+ if (toAccount != null) {
+ try {
+ toAccount.setBalance(toAccount.getBalance() + Long.decode(amount));
+ entityManager.merge(toAccount);
+ final Account fromAccount = entityManager.find(Account.class, from);
+ fromAccount.setBalance(fromAccount.getBalance() - Long.decode(amount));
+ if (fromAccount.getBalance() < 0) {
+ throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+ .entity("Transaction failed. Not enough money on the funding account.").build());
+ }
+ entityManager.merge(fromAccount);
+ return "Transaction sucessful.";
+ } catch (Exception e) {
+ if (e instanceof WebApplicationException) {
+ throw (WebApplicationException) e;
+ } else {
+ throw new WebApplicationException(
+ Response.status(Response.Status.BAD_REQUEST).entity("Something bad happened.").build());
+ }
+ }
+ } else {
+ throw new WebApplicationException(
+ Response.status(Response.Status.BAD_REQUEST).entity("Target account not found.").build());
+ }
+ }
+}
diff --git a/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/TestApplication.java b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/TestApplication.java
new file mode 100644
index 0000000..8e3f6d0
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/java/org/glassfish/jersey/tests/integration/jersey2137/TestApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2137;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources for JERSEY-2137 reproducer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class TestApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(CdiTransactionalResource.class);
+ classes.add(CdiTransactionalNoRollbackResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/jersey-2137/src/main/webapp/WEB-INF/beans.xml b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/jersey-2137/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3c18370
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+</web-app>
diff --git a/tests/integration/jersey-2137/src/main/webapp/WEB-INF/weblogic.xml b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/weblogic.xml
new file mode 100644
index 0000000..1d2a9ef
--- /dev/null
+++ b/tests/integration/jersey-2137/src/main/webapp/WEB-INF/weblogic.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
+
+ <wls:library-ref>
+ <wls:library-name>jax-rs</wls:library-name>
+ <wls:specification-version>2.0</wls:specification-version>
+ <wls:exact-match>true</wls:exact-match>
+ </wls:library-ref>
+</wls:weblogic-web-app>
diff --git a/tests/integration/jersey-2137/src/test/java/org/glassfish/jersey/tests/integration/jersey2137/WaeExceptionMappingTest.java b/tests/integration/jersey-2137/src/test/java/org/glassfish/jersey/tests/integration/jersey2137/WaeExceptionMappingTest.java
new file mode 100644
index 0000000..c722b92
--- /dev/null
+++ b/tests/integration/jersey-2137/src/test/java/org/glassfish/jersey/tests/integration/jersey2137/WaeExceptionMappingTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2137;
+
+import java.net.URI;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.equalTo;
+
+/**
+ * Reproducer for JERSEY-2137.
+ * Ensure that generated {@link WebApplicationException} is propagated
+ * via transactional CDI call and mapped to response according to JAX-RS spec.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class WaeExceptionMappingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("jersey-2137").build();
+ }
+
+ /**
+ * Test all {@javax.transaction.Transactional}
+ * annotated CDI beans. The test scenario is as follows.
+ * Set two accounts via the CDI bean that avoids rollback.
+ * Should any rollback happen there, we would not be able
+ * to store any data in JPA. Next try to make two transactions,
+ * first of them should be finished without errors,
+ * during the other one, a rollback is expected.
+ * The rollback should avoid partial data to be written
+ * to the first account.
+ */
+ @Test
+ public void testTransactions() {
+
+ final WebTarget cdiResource = target().path("cdi-transactional");
+ final WebTarget cdiResourceNoRollback = target().path("cdi-transactional-no-rollback");
+
+ Response response;
+ String responseBody;
+
+ // account 12 -> insert 1000:
+ response = cdiResourceNoRollback.path("12").request().put(Entity.text("1000"));
+ assertThat(response.getStatus(), equalTo(200));
+
+ // account 13 -> insert 1000:
+ response = cdiResourceNoRollback.path("13").request().put(Entity.text("1000"));
+ assertThat(response.getStatus(), equalTo(200));
+
+ // transfer 1000 from 13 to 12:
+ response = cdiResource.queryParam("from", "13").queryParam("to", "12").request().post(Entity.text("1000"));
+ assertThat(response.getStatus(), equalTo(200));
+
+ // ensure 12 has balance 2000:
+ response = cdiResource.path("12").request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ responseBody = response.readEntity(String.class);
+ assertThat(responseBody, equalTo("2000"));
+
+ // try to transfer 1000 from non-existing 8 to 12, this time the transaction should fail:
+ response = cdiResource.queryParam("from", "8").queryParam("to", "12").request().post(Entity.text("1000"));
+ assertThat(response.getStatus(), equalTo(400));
+
+ // ensure 12 balance has not changed:
+ response = cdiResource.path("12").request().get();
+ assertThat(response.getStatus(), equalTo(200));
+ responseBody = response.readEntity(String.class);
+ assertThat(responseBody, equalTo("2000"));
+ }
+}
diff --git a/tests/integration/jersey-2154/pom.xml b/tests/integration/jersey-2154/pom.xml
new file mode 100644
index 0000000..6dc290f
--- /dev/null
+++ b/tests/integration/jersey-2154/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2154</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2154</name>
+
+ <description>Jersey CDI/EJB test web application, JERSEY-2154 reproducer</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>javax.ejb-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/CdiResource.java b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/CdiResource.java
new file mode 100644
index 0000000..8539fc7
--- /dev/null
+++ b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/CdiResource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2154;
+
+import javax.ejb.EJB;
+import javax.enterprise.context.RequestScoped;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * Request scoped CDI bean injected with EJB bean.
+ * Part of JERSEY-2154 reproducer. {@link javax.ejb.EJBException}
+ * thrown in the injected EJB bean should get unwrapped
+ * even when no EJB-backed JAX-RS resources have been registered.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RequestScoped
+@Path("cdi")
+public class CdiResource {
+
+ @EJB EjbBean ejbBean;
+
+ @GET
+ public String get() {
+ return ejbBean.exceptionDrivenResponse();
+ }
+}
diff --git a/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/EjbBean.java b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/EjbBean.java
new file mode 100644
index 0000000..bd19227
--- /dev/null
+++ b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/EjbBean.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2154;
+
+import javax.ejb.EJBException;
+import javax.ejb.Stateless;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+/**
+ * EJB bean to reproduce JERSEY-2154. Bellow generated {@link WebApplicationException}
+ * should get mapped to response even when wrapped into an {@link EJBException}
+ * by the underlying EJB container.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Stateless
+public class EjbBean {
+
+ /**
+ * This is to make sure the exception thrown gets wrapped with an {@link EJBException}.
+ *
+ * @return nothing, just throws an exception.
+ */
+ public String exceptionDrivenResponse() {
+ throw new WebApplicationException(Response.ok("If you read this, the exception got mapped successfully!").build());
+ }
+}
diff --git a/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/TestApplication.java b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/TestApplication.java
new file mode 100644
index 0000000..a794af9
--- /dev/null
+++ b/tests/integration/jersey-2154/src/main/java/org/glassfish/jersey/tests/integration/jersey2154/TestApplication.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2154;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources for JERSEY-2154 reproducer.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("/*")
+public class TestApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(CdiResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/jersey-2154/src/main/webapp/WEB-INF/beans.xml b/tests/integration/jersey-2154/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..07df368
--- /dev/null
+++ b/tests/integration/jersey-2154/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans/>
diff --git a/tests/integration/jersey-2154/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2154/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3c18370
--- /dev/null
+++ b/tests/integration/jersey-2154/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+</web-app>
diff --git a/tests/integration/jersey-2154/src/test/java/org/glassfish/jersey/tests/integration/jersey2154/EjbExceptionMappingTest.java b/tests/integration/jersey-2154/src/test/java/org/glassfish/jersey/tests/integration/jersey2154/EjbExceptionMappingTest.java
new file mode 100644
index 0000000..564fc14
--- /dev/null
+++ b/tests/integration/jersey-2154/src/test/java/org/glassfish/jersey/tests/integration/jersey2154/EjbExceptionMappingTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2154;
+
+import java.net.URI;
+import javax.ejb.EJBException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.StringContains.containsString;
+
+/**
+ * Reproducer for JERSEY-2154.
+ * Test generated {@link WebApplicationException} is propagated
+ * via CDI call and mapped to 200 response, even when wrapped with an {@link EJBException}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class EjbExceptionMappingTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("jersey-2154").build();
+ }
+
+ /**
+ * The only test needed. Should the original {@link WebApplicationException}
+ * not get unwrapped, we would end up with 500 status code.
+ */
+ @Test
+ public void testInjection() {
+
+ final WebTarget cdiResource = target().path("cdi");
+
+ Response response = cdiResource.request().get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), containsString("exception got mapped"));
+ }
+}
diff --git a/tests/integration/jersey-2160/pom.xml b/tests/integration/jersey-2160/pom.xml
new file mode 100644
index 0000000..8e32aac
--- /dev/null
+++ b/tests/integration/jersey-2160/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2160</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2160</name>
+
+ <description>Servlet integration test - JERSEY-2160 - HttpServletRequest/HttpServletResponse do not get injected as a proxy into method parameters</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Issue2160ReproducerResource.java b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Issue2160ReproducerResource.java
new file mode 100644
index 0000000..2097ef2
--- /dev/null
+++ b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Issue2160ReproducerResource.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2160;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.hk2.api.ProxyCtl;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("servletInjectees")
+public class Issue2160ReproducerResource {
+
+ @Context
+ HttpServletRequest requestField;
+ @Context
+ HttpServletResponse responseField;
+
+ @GET
+ @Produces("text/plain")
+ public String ensureNoProxyInjected(@Context HttpServletRequest requestParam, @Context HttpServletResponse responseParam) {
+
+ // make sure the injectees are same no matter how they got injected
+ if (requestParam != requestField || responseParam != responseField) {
+ throw new IllegalArgumentException("injected field and parameter should refer to the same instance");
+ }
+
+ // make sure we have not got proxies
+ if (requestParam instanceof ProxyCtl || responseParam instanceof ProxyCtl) {
+ throw new IllegalArgumentException("no proxy expected!");
+ }
+
+ return (String) requestParam.getAttribute(RequestFilter.REQUEST_NUMBER_PROPERTY);
+ }
+}
diff --git a/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160App.java b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160App.java
new file mode 100644
index 0000000..29f21c6
--- /dev/null
+++ b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160App.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2160;
+
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import java.util.HashSet;
+
+/**
+ * JAX-RS application for the JERSEY-1960 reproducer test.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Jersey2160App extends Application {
+
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {
+ {
+ add(RequestFilter.class);
+ add(Issue2160ReproducerResource.class);
+ }
+ };
+ }
+}
diff --git a/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/RequestFilter.java b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/RequestFilter.java
new file mode 100644
index 0000000..8a44f0c
--- /dev/null
+++ b/tests/integration/jersey-2160/src/main/java/org/glassfish/jersey/tests/integration/jersey2160/RequestFilter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2160;
+
+import java.io.IOException;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Filter that set a property on actual request. The property value
+ * is expected to be propagated to the resource method via injected
+ * {@link HttpServletRequest} parameter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@PreMatching
+public class RequestFilter implements ContainerRequestFilter {
+
+ public static final String REQUEST_NUMBER_PROPERTY = "request-number";
+ public static final String REQUEST_NUMBER_HEADER = "number";
+
+ @Override
+ public void filter(ContainerRequestContext ctx) throws IOException {
+ final String number = ctx.getHeaderString(REQUEST_NUMBER_HEADER);
+ ctx.setProperty(REQUEST_NUMBER_PROPERTY, number);
+ }
+}
diff --git a/tests/integration/jersey-2160/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2160/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3b97459
--- /dev/null
+++ b/tests/integration/jersey-2160/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2160Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2160.Jersey2160App</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2160Servlet</servlet-name>
+ <url-pattern>/jersey-2160/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2160/src/test/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160ITCase.java b/tests/integration/jersey-2160/src/test/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160ITCase.java
new file mode 100644
index 0000000..dd7f0b5
--- /dev/null
+++ b/tests/integration/jersey-2160/src/test/java/org/glassfish/jersey/tests/integration/jersey2160/Jersey2160ITCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2160;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer tests for JERSEY-2160.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Jersey2160ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2160App();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Reproducer method for JERSEY-2160.
+ */
+ @Test
+ public void testJersey2160Fix() {
+ for (int i = 0; i < 10; i++) {
+ String response = target().path("jersey-2160/servletInjectees")
+ .request().header(RequestFilter.REQUEST_NUMBER_HEADER, i)
+ .get(String.class);
+ assertEquals(Integer.parseInt(response), i);
+ }
+ }
+}
diff --git a/tests/integration/jersey-2164/pom.xml b/tests/integration/jersey-2164/pom.xml
new file mode 100644
index 0000000..24f6782
--- /dev/null
+++ b/tests/integration/jersey-2164/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2164</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2164</name>
+
+ <description>Servlet integration test - JERSEY-2164 - Multi value http headers are not correctly read by the server</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Issue2164Resource.java b/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Issue2164Resource.java
new file mode 100644
index 0000000..40b9da4
--- /dev/null
+++ b/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Issue2164Resource.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2164;
+
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+
+/**
+ * Test resource.
+ *
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Issue2164Resource {
+
+ @GET
+ public String get(@HeaderParam("hello") final List<String> headers) {
+ return headers.size() + ":" + headers;
+ }
+}
diff --git a/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164.java b/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164.java
new file mode 100644
index 0000000..0b4cff4
--- /dev/null
+++ b/tests/integration/jersey-2164/src/main/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2164;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2164 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2164 extends ResourceConfig {
+
+ public Jersey2164() {
+ register(Issue2164Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-2164/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2164/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..8b77a93
--- /dev/null
+++ b/tests/integration/jersey-2164/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2164Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2164.Jersey2164</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2164Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2164/src/test/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164ITCase.java b/tests/integration/jersey-2164/src/test/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164ITCase.java
new file mode 100644
index 0000000..79c24c9
--- /dev/null
+++ b/tests/integration/jersey-2164/src/test/java/org/glassfish/jersey/tests/integration/jersey2164/Jersey2164ITCase.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2164;
+
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2164.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2164ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2164();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHeaderListSingleHeader() throws Exception {
+ Response response = target().request().header("hello", "world").header("hello", "universe").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("1:[world,universe]"));
+ }
+
+ /**
+ * Check that multi value http headers are correctly read by the server.
+ */
+ @Test
+ public void testHeaderListMultipleHeaders() throws Exception {
+ final URL url = new URL(getBaseUri().toString());
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.setRequestProperty("hello", "world");
+ connection.addRequestProperty("hello", "universe");
+
+ connection.setDoOutput(false);
+ connection.connect();
+
+ assertThat(connection.getResponseCode(), equalTo(200));
+ assertThat(ReaderWriter.readFromAsString(new InputStreamReader(connection.getInputStream())),
+ equalTo("2:[world, universe]"));
+ }
+}
diff --git a/tests/integration/jersey-2167/pom.xml b/tests/integration/jersey-2167/pom.xml
new file mode 100644
index 0000000..943e894
--- /dev/null
+++ b/tests/integration/jersey-2167/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2167</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2167</name>
+
+ <description>JERSEY-2167 reproducer - Injecting a custom parameter type causes REST method to run twice</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Issue2167Resource.java b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Issue2167Resource.java
new file mode 100644
index 0000000..48ccef8
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Issue2167Resource.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Test resource for JERSEY-2167 reproducer.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+
+@Path("/MyResource")
+public class Issue2167Resource {
+ private static final Logger LOGGER = Logger.getLogger(Issue2167Resource.class.getName());
+ public static final String MSG = "Resource method doA() called at ";
+
+ @Path("test")
+ @GET
+ public Response doA(@MyAnnotation String param) {
+ LOGGER.log(Level.INFO, MSG + System.currentTimeMillis() + "; param=" + param);
+ if (param == null) {
+ return Response.serverError().build();
+ }
+ return Response.ok().build();
+ }
+}
diff --git a/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167App.java b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167App.java
new file mode 100644
index 0000000..1adc3cc
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167App.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2167 reproducer test.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class Jersey2167App extends ResourceConfig {
+
+ public Jersey2167App() {
+ register(Issue2167Resource.class);
+ register(new MyBinder());
+ }
+}
diff --git a/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyAnnotation.java b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyAnnotation.java
new file mode 100644
index 0000000..edec66e
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyAnnotation.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Custom annotation for JERSEY-2167 reproducer test.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MyAnnotation {
+}
diff --git a/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyBinder.java b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyBinder.java
new file mode 100644
index 0000000..b6de2c8
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyBinder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
+
+/**
+ * Custom annotation binder for JERSEY-2167 reproducer.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MyBinder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ bind(MyValueParamProvider.class).to(ValueParamProvider.class).in(Singleton.class);
+ }
+}
diff --git a/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyValueParamProvider.java b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyValueParamProvider.java
new file mode 100644
index 0000000..5eae5ae
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/java/org/glassfish/jersey/tests/integration/jersey2167/MyValueParamProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import java.util.function.Function;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
+import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
+import org.glassfish.jersey.server.model.Parameter;
+
+/**
+ * Custom annotation value supplier provider for JERSEY-2167 reproducer.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Singleton
+public class MyValueParamProvider extends AbstractValueParamProvider {
+
+ @Inject
+ public MyValueParamProvider(Provider<MultivaluedParameterExtractorProvider> mpep) {
+ super(mpep, Parameter.Source.UNKNOWN);
+ }
+
+ @Override
+ protected Function<ContainerRequest, ?> createValueProvider(Parameter parameter) {
+ return new MyValueSupplier();
+ }
+
+ private static final class MyValueSupplier implements Function<ContainerRequest, Object> {
+
+ @Override
+ public Object apply(ContainerRequest request) {
+ // returns some testing value
+ return "injected timestamp=" + System.currentTimeMillis();
+ }
+ }
+}
diff --git a/tests/integration/jersey-2167/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2167/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..be1fb9d
--- /dev/null
+++ b/tests/integration/jersey-2167/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2167Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2167.Jersey2167App</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2167Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2167/src/test/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167ITCase.java b/tests/integration/jersey-2167/src/test/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167ITCase.java
new file mode 100644
index 0000000..cff58c6
--- /dev/null
+++ b/tests/integration/jersey-2167/src/test/java/org/glassfish/jersey/tests/integration/jersey2167/Jersey2167ITCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2167;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer tests for JERSEY-2167.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class Jersey2167ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new Jersey2167App();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceMethodCall() throws Exception {
+ Response response = target().path("MyResource/test").request().get();
+ // if parameter was not injected, resource returns Response.Status.SERVER_ERROR (500). Missing parameter means,
+ // that hk2 injected the parameter and invoked the method preliminary and during Jersey-driven invocation,
+ // there was no parameter injection any more. If parameter was injected and Response.Status.OK (200) returned,
+ // the resource method was called only once (by Jersey).
+ assertEquals("Parameter not injected into resource method. Resource method could have been called twice. ",
+ response.getStatus(), Response.Status.OK.getStatusCode());
+ }
+}
diff --git a/tests/integration/jersey-2176/pom.xml b/tests/integration/jersey-2176/pom.xml
new file mode 100644
index 0000000..c4c3877
--- /dev/null
+++ b/tests/integration/jersey-2176/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2176</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2176</name>
+
+ <description>Servlet integration test - JERSEY-2176 - Problems with calling close() and flush()
+ methods on underlying output stream.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Issue2176ReproducerResource.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Issue2176ReproducerResource.java
new file mode 100644
index 0000000..6b0d093
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Issue2176ReproducerResource.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+/**
+ * Test resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("/resource")
+public class Issue2176ReproducerResource {
+
+ static final String X_FAIL_HEADER = "X-FAIL";
+ static final String X_RESPONSE_ENTITY_HEADER = "X-RESPONSE-ENTITY";
+
+ @GET
+ @Produces("text/plain")
+ @Path("{status}")
+ public Response getText(@PathParam("status") int uc,
+ @Context HttpHeaders headers) throws MyException {
+ if (uc == -1) {
+ throw new MyException("UC= " + uc);
+ } else if (uc == -2) {
+ throw new IllegalStateException("UC= " + uc);
+ } else if (uc == -3) {
+ throw new WebApplicationException("UC= " + uc, 321);
+ } else if (uc == -4) {
+ throw new WebApplicationException("UC= " + uc, 432);
+ }
+
+ final Response.ResponseBuilder responseBuilder = Response.status(uc);
+ if (headers.getRequestHeaders().containsKey(X_RESPONSE_ENTITY_HEADER)) {
+ responseBuilder.entity("ENTITY");
+ }
+ final Response response = responseBuilder.build();
+ if (headers.getRequestHeaders().containsKey(X_RESPONSE_ENTITY_HEADER)) {
+ response.getHeaders().add(X_RESPONSE_ENTITY_HEADER, "true");
+ }
+ if (headers.getRequestHeaders().containsKey(X_FAIL_HEADER)) {
+ response.getHeaders().add(X_FAIL_HEADER, "true");
+ }
+ return response;
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java
new file mode 100644
index 0000000..e28cfc2
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * JAX-RS application for the JERSEY-2176 reproducer test.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+abstract class Jersey2176App extends ResourceConfig {
+
+ private final boolean setStatusOverSendError;
+
+ public Jersey2176App(boolean setStatusOverSendError) {
+ this.setStatusOverSendError = setStatusOverSendError;
+
+ property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, setStatusOverSendError);
+ register(MyWriterInterceptor.class);
+ register(Issue2176ReproducerResource.class);
+ }
+
+ public boolean isSetStatusOverSendError() {
+ return setStatusOverSendError;
+ }
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorApp.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorApp.java
new file mode 100644
index 0000000..dcdcaed
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorApp.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.ApplicationPath;
+
+/**
+ * Configure {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR} by {@code true} -
+ * method {@link javax.servlet.http.HttpServletResponse#sendError} will be called in case of errors
+ * (status {@code 4xx} or {@code 5xx}).
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath(Jersey2176SendErrorApp.APP_PATH)
+public class Jersey2176SendErrorApp extends Jersey2176App {
+
+ public static final String APP_PATH = "send-error";
+
+ public Jersey2176SendErrorApp() {
+ super(false);
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusApp.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusApp.java
new file mode 100644
index 0000000..501df02
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusApp.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.ApplicationPath;
+
+/**
+ * Configure {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR} by {@code true} -
+ * method {@link javax.servlet.http.HttpServletResponse#setStatus} will be called in case of errors
+ * (status {@code 4xx} or {@code 5xx}).
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath(Jersey2176SetStatusApp.APP_PATH)
+public class Jersey2176SetStatusApp extends Jersey2176App {
+
+ public static final String APP_PATH = "set-status";
+
+ public Jersey2176SetStatusApp() {
+ super(true);
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyException.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyException.java
new file mode 100644
index 0000000..e7daf21
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class MyException extends Exception {
+
+ public MyException(String message) {
+ super(message);
+ }
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyWriterInterceptor.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyWriterInterceptor.java
new file mode 100644
index 0000000..f4a4fcd
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/MyWriterInterceptor.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+
+/**
+ * This just set new context output stream and test a clone method on set output stream instance is called.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class MyWriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException {
+ final boolean fail = context.getHeaders().containsKey(Issue2176ReproducerResource.X_FAIL_HEADER);
+ final boolean responseEntity = context.getHeaders().containsKey(Issue2176ReproducerResource.X_RESPONSE_ENTITY_HEADER);
+
+ if (responseEntity) {
+ context.setOutputStream(
+ new MyOutputStream(context.getOutputStream(), MessageUtils.getCharset(context.getMediaType())));
+ }
+ context.proceed();
+ if (fail) {
+ throw new IllegalStateException("From MyWriterInterceptor");
+ }
+ }
+
+ private static class MyOutputStream extends OutputStream {
+ private final OutputStream delegate;
+ final Charset charset;
+ private final ByteArrayOutputStream localStream;
+
+ private MyOutputStream(final OutputStream delegate, final Charset charset) throws IOException {
+ this.delegate = delegate;
+ this.charset = charset;
+
+ this.localStream = new ByteArrayOutputStream();
+ localStream.write("[INTERCEPTOR]".getBytes(charset));
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ localStream.write(b);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ delegate.write(localStream.toByteArray());
+ localStream.reset();
+ delegate.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ localStream.write("[/INTERCEPTOR]".getBytes(charset));
+
+ delegate.write(localStream.toByteArray());
+
+ delegate.close();
+ localStream.close();
+ }
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java
new file mode 100644
index 0000000..c20ecf3
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TraceResponseFilter implements Filter {
+
+ public static final String X_SERVER_DURATION_HEADER = "X-SERVER-DURATION";
+ public static final String X_STATUS_HEADER = "X-STATUS";
+ public static final String X_NO_FILTER_HEADER = "X-NO-FILTER";
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void doFilter(final ServletRequest request, ServletResponse response, final FilterChain chain)
+ throws IOException, ServletException {
+ TraceResponseWrapper wrappedResponse = null;
+ if (((HttpServletRequest) request).getHeader(X_NO_FILTER_HEADER) == null) {
+ response = wrappedResponse = new TraceResponseWrapper((HttpServletResponse) response);
+ }
+ String status = "n/a";
+ final long startTime = System.nanoTime();
+ try {
+ chain.doFilter(request, response);
+ status = "OK";
+ } catch (final Throwable th) {
+ status = "FAIL";
+ } finally {
+ final long duration = System.nanoTime() - startTime;
+ ((HttpServletResponse) response).addHeader(X_SERVER_DURATION_HEADER, String.valueOf(duration));
+ ((HttpServletResponse) response).addHeader(X_STATUS_HEADER, status);
+ if (wrappedResponse != null) {
+ ((HttpServletResponse) response).setHeader(HttpHeaders.CONTENT_LENGTH, wrappedResponse.getContentLength());
+ wrappedResponse.writeBodyAndClose(response.getCharacterEncoding());
+ }
+ }
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseWrapper.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseWrapper.java
new file mode 100644
index 0000000..3e2f672
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseWrapper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TraceResponseWrapper extends HttpServletResponseWrapper {
+ private final ByteArrayOutputStream localStream;
+
+ public TraceResponseWrapper(final HttpServletResponse response) throws IOException {
+ super(response);
+
+ localStream = new ByteArrayOutputStream();
+ localStream.write("[FILTER]".getBytes(response.getCharacterEncoding()));
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return new ServletOutputStream() {
+ @Override
+ public void write(final int b) throws IOException {
+ localStream.write(b);
+ }
+ };
+ }
+
+ public void writeBodyAndClose(final String encoding) throws IOException {
+ localStream.write("[/FILTER]".getBytes(encoding));
+
+ super.getOutputStream().write(localStream.toByteArray());
+ super.getOutputStream().close();
+ localStream.close();
+ }
+
+ public String getContentLength() {
+ return String.valueOf(localStream.size() + "[/FILTER]".length());
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2176/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ac9109f
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>TraceFilter</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.jersey2176.TraceResponseFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>TraceFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ITCaseBase.java b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ITCaseBase.java
new file mode 100644
index 0000000..ffeec36
--- /dev/null
+++ b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ITCaseBase.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Reproducer tests for JERSEY-2176.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public abstract class Jersey2176ITCaseBase extends JerseyTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testGetContent222() {
+ testGetContent(222, true);
+ }
+
+ @Test
+ public void testGetContent333() {
+ testGetContent(333, true);
+ }
+
+ @Test
+ public void testGetContent444() {
+ testGetContent(444, true);
+ }
+
+ @Test
+ public void testGetContent555() {
+ testGetContent(555, true);
+ }
+
+ @Test
+ public void testGetContent222NoResponseEntity() {
+ testGetContent(222, false);
+ }
+
+ @Test
+ public void testGetContent333NoResponseEntity() {
+ testGetContent(333, false);
+ }
+
+ @Test
+ public void testGetContent444NoResponseEntity() {
+ testGetContent(444, false);
+ }
+
+ @Test
+ public void testGetContent555NoResponseEntity() {
+ testGetContent(555, false);
+ }
+
+ @Test
+ public void testGetException_1() {
+ testGetException(-1, 500, false);
+ }
+
+ @Test
+ public void testGetException_2() {
+ testGetException(-2, 500, false);
+ }
+
+ @Test
+ public void testGetException_3() {
+ testGetException(-3, 321, false);
+ }
+
+ @Test
+ public void testGetException_4() {
+ testGetException(-4, 432, false);
+ }
+
+ @Test
+ public void testGetException222() {
+ testGetException(222, 500, true);
+ }
+
+ private void testGetContent(int uc, boolean responseEntity) {
+ String expectedContent = "ENTITY";
+ expectedContent = "[INTERCEPTOR]" + expectedContent + "[/INTERCEPTOR]";
+ expectedContent = "[FILTER]" + expectedContent + "[/FILTER]";
+
+ Invocation.Builder builder = target().path("/resource/" + uc).request();
+ if (responseEntity) {
+ builder.header(Issue2176ReproducerResource.X_RESPONSE_ENTITY_HEADER, true);
+ } else {
+ builder.header(TraceResponseFilter.X_NO_FILTER_HEADER, true);
+ }
+
+ final Response response = builder.get();
+ final String assertMessage = uc + "|" + responseEntity;
+
+ Assert.assertEquals(assertMessage, uc, response.getStatus());
+ if (!sendErrorExpected(uc, responseEntity)) {
+ Assert.assertEquals(assertMessage, "OK", response.getHeaderString(TraceResponseFilter.X_STATUS_HEADER));
+ Assert.assertNotNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_SERVER_DURATION_HEADER));
+ if (responseEntity) {
+ Assert.assertEquals(assertMessage, expectedContent, response.readEntity(String.class));
+ Assert.assertEquals(assertMessage, String.valueOf(expectedContent.length()),
+ response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ }
+ } else {
+ Assert.assertNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_STATUS_HEADER));
+ Assert.assertNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_SERVER_DURATION_HEADER));
+ }
+ }
+
+ private void testGetException(int uc, int expectedStatus, boolean fail) {
+ Invocation.Builder builder = target().path("/resource/" + uc).request();
+ builder = builder.header(Issue2176ReproducerResource.X_RESPONSE_ENTITY_HEADER, true);
+ if (fail) {
+ builder = builder.header(Issue2176ReproducerResource.X_FAIL_HEADER, true);
+ }
+
+ final Response response = builder.get();
+
+ final String expectedContent = "[FILTER][/FILTER]";
+ final String assertMessage = uc + ":" + expectedStatus + "|" + fail;
+
+ Assert.assertEquals(assertMessage, expectedStatus, response.getStatus());
+ if (!sendErrorExpected(expectedStatus, false)) {
+ Assert.assertEquals(assertMessage, expectedStatus == 500 ? "FAIL" : "OK",
+ response.getHeaderString(TraceResponseFilter.X_STATUS_HEADER));
+ Assert.assertNotNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_SERVER_DURATION_HEADER));
+ Assert.assertEquals(assertMessage, String.valueOf(expectedContent.length()),
+ response.getHeaderString(HttpHeaders.CONTENT_LENGTH));
+ } else {
+ Assert.assertNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_STATUS_HEADER));
+ Assert.assertNull(assertMessage, response.getHeaderString(TraceResponseFilter.X_SERVER_DURATION_HEADER));
+ }
+ }
+
+ private boolean sendErrorExpected(final int uc, final boolean responseEntity) {
+ return !((Jersey2176App) configure()).isSetStatusOverSendError() && (uc >= 400) && !responseEntity;
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorITCase.java b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorITCase.java
new file mode 100644
index 0000000..9eb2648
--- /dev/null
+++ b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SendErrorITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+
+/**
+ * Reproducer tests for JERSEY-2176.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Jersey2176SendErrorITCase extends Jersey2176ITCaseBase {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2176SendErrorApp();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path(Jersey2176SendErrorApp.APP_PATH).build();
+ }
+
+}
diff --git a/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusITCase.java b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusITCase.java
new file mode 100644
index 0000000..f894ee0
--- /dev/null
+++ b/tests/integration/jersey-2176/src/test/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176SetStatusITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2176;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+
+/**
+ * Reproducer tests for JERSEY-2176.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Jersey2176SetStatusITCase extends Jersey2176ITCaseBase {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2176SetStatusApp();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path(Jersey2176SetStatusApp.APP_PATH).build();
+ }
+
+}
diff --git a/tests/integration/jersey-2184/pom.xml b/tests/integration/jersey-2184/pom.xml
new file mode 100644
index 0000000..255156d
--- /dev/null
+++ b/tests/integration/jersey-2184/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2184</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2184</name>
+
+ <description>
+ Servlet integration test - JERSEY-2184 - ServletContext injection into Application subclass constructor.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/App.java b/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/App.java
new file mode 100644
index 0000000..04a279f
--- /dev/null
+++ b/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/App.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2184;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Test Application subclass for JERSEY-2184 integration test.
+ *
+ * Tests the ability to inject {@link ServletContext} into application subclass constructor
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class App extends Application {
+
+ /** constructor-injected servletContext */
+ private ServletContext ctx;
+
+ public App(@Context ServletContext servletContext) {
+ this.ctx = servletContext;
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ HashSet<Class<?>> classes = new HashSet<>();
+ String dynamicClassName = ctx.getInitParameter("dynamicClassName");
+ Class<?> clazz = null;
+ if (classes.isEmpty()) {
+ try {
+ clazz = Class.forName(dynamicClassName);
+ } catch (ClassNotFoundException e) {
+ // swallow the exception - if class is not loaded, the integration test will fail
+ }
+
+ if (clazz != null) {
+ classes.add(clazz);
+ }
+ }
+ return classes;
+ }
+}
diff --git a/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/MonkeyResource.java b/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/MonkeyResource.java
new file mode 100644
index 0000000..bd9356b
--- /dev/null
+++ b/tests/integration/jersey-2184/src/main/java/org/glassfish/jersey/tests/integration/jersey2184/MonkeyResource.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2184;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource for the servlet3-webapp example.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("monkey")
+public class MonkeyResource {
+ @GET
+ @Produces("text/plain")
+ public String chatter() {
+ return "Oooh!";
+ }
+}
diff --git a/tests/integration/jersey-2184/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2184/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..98b165c
--- /dev/null
+++ b/tests/integration/jersey-2184/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.jersey2184.App</servlet-name>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.jersey2184.App</servlet-name>
+ <url-pattern>/zoo/*</url-pattern>
+ </servlet-mapping>
+ <context-param>
+ <description>Context parameter to test the correct ServletContext injection into Application subclass.</description>
+ <param-name>dynamicClassName</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2184.MonkeyResource</param-value>
+ </context-param>
+</web-app>
+
diff --git a/tests/integration/jersey-2184/src/test/java/org/glassfish/jersey/tests/integration/jersey2184/Jersey2184ITCase.java b/tests/integration/jersey-2184/src/test/java/org/glassfish/jersey/tests/integration/jersey2184/Jersey2184ITCase.java
new file mode 100644
index 0000000..794203d
--- /dev/null
+++ b/tests/integration/jersey-2184/src/test/java/org/glassfish/jersey/tests/integration/jersey2184/Jersey2184ITCase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2184;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the JERSEY-2184 fix (the ability to inject ServletContext into application subclass constructor).
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class Jersey2184ITCase extends JerseyTest {
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ return new Application(); // dummy Application instance for the test framework - will no be used.
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ return UriBuilder.fromUri(super.getBaseUri()).path("zoo").build();
+ }
+
+ /**
+ * Tests if {@link javax.servlet.ServletContext} has been correctly injected into {@link App} constructor parameter;
+ * The resource under this URL is being loaded dynamically based on a context parameter in the web.xml,
+ * so if injection fails, the resource will not be available.
+ */
+ @Test
+ public void testInjection() {
+ String s = target().path("monkey").request().get(String.class);
+ assertEquals("Oooh!", s);
+ }
+}
diff --git a/tests/integration/jersey-2255/pom.xml b/tests/integration/jersey-2255/pom.xml
new file mode 100644
index 0000000..3b1f2ad
--- /dev/null
+++ b/tests/integration/jersey-2255/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2255</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2255</name>
+
+ <description>Filtering hierarchy test - JERSEY-2255 - Entity Data Filtering should support inherited fields</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Issue2255Resource.java b/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Issue2255Resource.java
new file mode 100644
index 0000000..0ac2f37
--- /dev/null
+++ b/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Issue2255Resource.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2255;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * Test resource.
+ *
+ * @author Eric Miles (emilesvt at gmail.com)
+ */
+@Path("/")
+@Consumes("application/json")
+@Produces("application/json")
+public class Issue2255Resource {
+
+ public static class A {
+
+ public A() {
+ }
+
+ public A(String fieldA1) {
+ this.fieldA1 = fieldA1;
+ }
+
+ private String fieldA1;
+
+ @Detailed
+ public String getFieldA1() {
+ return fieldA1;
+ }
+
+ public void setFieldA1(final String fieldA1) {
+ this.fieldA1 = fieldA1;
+ }
+ }
+
+ public static class B extends A {
+
+ public B() {
+ }
+
+ public B(String fieldA1, String fieldB1) {
+ super(fieldA1);
+ this.fieldB1 = fieldB1;
+ }
+
+ private String fieldB1;
+
+ public String getFieldB1() {
+ return fieldB1;
+ }
+
+ public void setFieldB1(final String fieldB1) {
+ this.fieldB1 = fieldB1;
+ }
+ }
+
+ @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ @EntityFiltering
+ public static @interface Detailed {
+
+ /**
+ * Factory class for creating instances of {@code ProjectDetailedView} annotation.
+ */
+ public static class Factory
+ extends AnnotationLiteral<Detailed>
+ implements Detailed {
+
+ private Factory() {
+ }
+
+ public static Detailed get() {
+ return new Factory();
+ }
+ }
+ }
+
+ @Path("A")
+ @GET
+ public Response getA(@QueryParam("detailed") final boolean isDetailed) {
+ return Response
+ .ok()
+ .entity(new A("fieldA1Value"), isDetailed ? new Annotation[] {Detailed.Factory.get()} : new Annotation[0])
+ .build();
+ }
+
+ @Path("B")
+ @GET
+ public Response getB(@QueryParam("detailed") final boolean isDetailed) {
+ return Response
+ .ok()
+ .entity(new B("fieldA1Value", "fieldB1Value"),
+ isDetailed ? new Annotation[] {Detailed.Factory.get()} : new Annotation[0])
+ .build();
+ }
+
+}
diff --git a/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255.java b/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255.java
new file mode 100644
index 0000000..a1dd1b3
--- /dev/null
+++ b/tests/integration/jersey-2255/src/main/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2255;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2255 reproducer test.
+ *
+ * @author Eric Miles (emilesvt at gmail.com)
+ */
+public class Jersey2255 extends ResourceConfig {
+
+ public Jersey2255() {
+ register(Issue2255Resource.class);
+ register(EntityFilteringFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2255/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2255/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b6b050c
--- /dev/null
+++ b/tests/integration/jersey-2255/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2255Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2255.Jersey2255</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2255Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2255/src/test/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255ITCase.java b/tests/integration/jersey-2255/src/test/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255ITCase.java
new file mode 100644
index 0000000..a996eba
--- /dev/null
+++ b/tests/integration/jersey-2255/src/test/java/org/glassfish/jersey/tests/integration/jersey2255/Jersey2255ITCase.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2255;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.jersey2255.Issue2255Resource.A;
+import org.glassfish.jersey.tests.integration.jersey2255.Issue2255Resource.B;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Reproducer tests for JERSEY-2255.
+ *
+ * @author Eric Miles (emilesvt at gmail.com)
+ */
+public class Jersey2255ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return new Jersey2255();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Server side response is wrapped, needs to be read to wrapper class.
+ */
+ @Test
+ public void testClassAGet() {
+ final Response response = target("A").request().get();
+ final A entity = response.readEntity(A.class);
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertNull(entity.getFieldA1());
+ }
+
+ @Test
+ public void testDetailedClassAGet() {
+ final Response response = target("A").queryParam("detailed", true).request().get();
+ final A entity = response.readEntity(A.class);
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(entity.getFieldA1(), equalTo("fieldA1Value"));
+ }
+
+ /**
+ * Server side response is returned as orig class.
+ */
+ @Test
+ public void testDetailedClassBGet() {
+ final Response response = target("B").queryParam("detailed", true).request().get();
+ final B entity = response.readEntity(B.class);
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(entity.getFieldA1(), equalTo("fieldA1Value"));
+ assertThat(entity.getFieldB1(), equalTo("fieldB1Value"));
+ }
+
+ @Test
+ public void testClassBGet() {
+ final Response response = target("B").request().get();
+ final B entity = response.readEntity(B.class);
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertNull(entity.getFieldA1());
+ assertThat(entity.getFieldB1(), equalTo("fieldB1Value"));
+ }
+}
diff --git a/tests/integration/jersey-2322/pom.xml b/tests/integration/jersey-2322/pom.xml
new file mode 100644
index 0000000..a64aa6b
--- /dev/null
+++ b/tests/integration/jersey-2322/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2322</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2322</name>
+
+ <description>Servlet integration test - JERSEY-2322 - No way to configure auto-discovered Jackson 2.x ObjectMapper</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-metainf-services</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Issue2322Resource.java b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Issue2322Resource.java
new file mode 100644
index 0000000..7e8b05f
--- /dev/null
+++ b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Issue2322Resource.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2322;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("/")
+@Consumes("application/json")
+@Produces("application/json")
+public class Issue2322Resource {
+
+ public static class JsonString1 {
+ private String value;
+
+ public JsonString1() {
+ }
+ public JsonString1(String value) {
+ this.value = value;
+ }
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+ public static class JsonString2 {
+ private String value;
+
+ public JsonString2() {
+ }
+ public JsonString2(String value) {
+ this.value = value;
+ }
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+ @Path("1")
+ @PUT
+ public JsonString1 put(final JsonString1 wrapper) {
+ return new JsonString1("Hello " + wrapper.getValue());
+ }
+
+ @Path("2")
+ @PUT
+ public JsonString2 put(final JsonString2 wrapper) {
+ return new JsonString2("Hi " + wrapper.getValue());
+ }
+
+}
diff --git a/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322.java b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322.java
new file mode 100644
index 0000000..1e79c1e
--- /dev/null
+++ b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2322;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2322 reproducer test.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Jersey2322 extends ResourceConfig {
+
+ public Jersey2322() {
+ register(Issue2322Resource.class);
+ register(JacksonFeature.class);
+ register(MyObjectMapperProvider.class);
+ }
+}
diff --git a/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/MyObjectMapperProvider.java b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/MyObjectMapperProvider.java
new file mode 100644
index 0000000..61fe632
--- /dev/null
+++ b/tests/integration/jersey-2322/src/main/java/org/glassfish/jersey/tests/integration/jersey2322/MyObjectMapperProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2322;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
+
+ @Override
+ public ObjectMapper getContext(Class<?> type) {
+ if (type == Issue2322Resource.JsonString1.class) {
+ ObjectMapper result = new ObjectMapper();
+ result.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
+ result.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
+ return result;
+ } else {
+ return new ObjectMapper();
+ }
+ }
+}
diff --git a/tests/integration/jersey-2322/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2322/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..727ad27
--- /dev/null
+++ b/tests/integration/jersey-2322/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2322Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2322.Jersey2322</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2322Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2322/src/test/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322ITCase.java b/tests/integration/jersey-2322/src/test/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322ITCase.java
new file mode 100644
index 0000000..4f973a9
--- /dev/null
+++ b/tests/integration/jersey-2322/src/test/java/org/glassfish/jersey/tests/integration/jersey2322/Jersey2322ITCase.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2322;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2322.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Jersey2322ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+ return new Jersey2322();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Server side response is wrapped, needs to be read to wrapper class.
+ */
+ @Test
+ public void testJackson2JsonPut1() {
+ final Response response = target("1").request().put(Entity.json(new Issue2322Resource.JsonString1("foo")));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(Wrapper1.class).getJsonString1().getValue(), equalTo("Hello foo"));
+ }
+
+ /**
+ * Server side response is returned as orig class.
+ */
+ @Test
+ public void testJackson2JsonPut2() {
+ final Response response = target("2").request().put(Entity.json(new Issue2322Resource.JsonString2("foo")));
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(Issue2322Resource.JsonString2.class).getValue(), equalTo("Hi foo"));
+ }
+
+
+ public static class Wrapper1 {
+ @JsonProperty("JsonString1")
+ Issue2322Resource.JsonString1 jsonString1;
+
+ public Issue2322Resource.JsonString1 getJsonString1() {
+ return jsonString1;
+ }
+
+ public void setJsonString1(Issue2322Resource.JsonString1 jsonString1) {
+ this.jsonString1 = jsonString1;
+ }
+ }
+
+}
diff --git a/tests/integration/jersey-2335/pom.xml b/tests/integration/jersey-2335/pom.xml
new file mode 100644
index 0000000..075bed8
--- /dev/null
+++ b/tests/integration/jersey-2335/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2335</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2335</name>
+
+ <description>Servlet integration test - JERSEY-2335 - Providers do not get injected properly</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-metainf-services</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/ConstructorInjectedProvider.java b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/ConstructorInjectedProvider.java
new file mode 100644
index 0000000..7f59d01
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/ConstructorInjectedProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2335;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * Constructor injected provider to prove that provider registered via meta-inf/services
+ * mechanism gets constructed via HK2 and so the constructor parameters are properly injected.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Produces("text/ctor-injected")
+public class ConstructorInjectedProvider implements MessageBodyWriter<String> {
+
+ Providers providers;
+
+ public ConstructorInjectedProvider(@Context final Providers providers) {
+ this.providers = providers;
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ final MessageBodyWriter<String> plainTextWriter =
+ providers.getMessageBodyWriter(String.class, genericType, annotations, MediaType.TEXT_PLAIN_TYPE);
+ entityStream.write("via ctor injected provider:".getBytes(MessageUtils.getCharset(mediaType)));
+ plainTextWriter.writeTo(t, type, genericType, annotations, mediaType, httpHeaders, entityStream);
+ }
+}
diff --git a/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/FieldInjectedProvider.java b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/FieldInjectedProvider.java
new file mode 100644
index 0000000..5c6bc08
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/FieldInjectedProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2335;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * Field injected provider to prove that provider registered via meta-inf/services
+ * mechanism gets injected via HK2.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Produces("text/field-injected")
+public class FieldInjectedProvider implements MessageBodyWriter<String> {
+
+ @Context Providers providers;
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type == String.class;
+ }
+
+ @Override
+ public long getSize(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ final MessageBodyWriter<String> plainTextWriter =
+ providers.getMessageBodyWriter(String.class, genericType, annotations, MediaType.TEXT_PLAIN_TYPE);
+ entityStream.write("via field injected provider:".getBytes(MessageUtils.getCharset(mediaType)));
+ plainTextWriter.writeTo(t, type, genericType, annotations, mediaType, httpHeaders, entityStream);
+ }
+}
diff --git a/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Issue2335Resource.java b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Issue2335Resource.java
new file mode 100644
index 0000000..c4a44f6
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Issue2335Resource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2335;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource that provides a simple text response.
+ * The response text then gets serialized using message body writer
+ * specified by media type.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/text")
+public class Issue2335Resource {
+
+ @GET
+ @Produces("text/*")
+ public String get() {
+ return "Hey";
+ }
+}
diff --git a/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335.java b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335.java
new file mode 100644
index 0000000..10ff7e2
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2335;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2335 reproducer test.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Jersey2335 extends ResourceConfig {
+
+ public Jersey2335() {
+ register(Issue2335Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-2335/src/main/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter b/tests/integration/jersey-2335/src/main/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter
new file mode 100644
index 0000000..f5bca8b
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/resources/META-INF/services/javax.ws.rs.ext.MessageBodyWriter
@@ -0,0 +1,2 @@
+org.glassfish.jersey.tests.integration.jersey2335.FieldInjectedProvider
+org.glassfish.jersey.tests.integration.jersey2335.ConstructorInjectedProvider
\ No newline at end of file
diff --git a/tests/integration/jersey-2335/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2335/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..26d8b4a
--- /dev/null
+++ b/tests/integration/jersey-2335/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2335Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2335.Jersey2335</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2335Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2335/src/test/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335ITCase.java b/tests/integration/jersey-2335/src/test/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335ITCase.java
new file mode 100644
index 0000000..dfa5732
--- /dev/null
+++ b/tests/integration/jersey-2335/src/test/java/org/glassfish/jersey/tests/integration/jersey2335/Jersey2335ITCase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2335;
+
+import java.net.ConnectException;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Reproducer tests for JERSEY-2335.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Jersey2335ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2335();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testGetFieldInjected() throws Exception {
+ final Response response = target().path("text").request().accept("text/field-injected").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("via field injected provider:Hey"));
+ }
+
+ @Test
+ public void testGetConstructorInjected() throws Exception {
+ final Response response = target().path("text").request().accept("text/ctor-injected").get();
+
+ assertThat(response.getStatus(), equalTo(200));
+ assertThat(response.readEntity(String.class), equalTo("via ctor injected provider:Hey"));
+ }
+}
diff --git a/tests/integration/jersey-2421/pom.xml b/tests/integration/jersey-2421/pom.xml
new file mode 100644
index 0000000..edae017
--- /dev/null
+++ b/tests/integration/jersey-2421/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2421</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2421</name>
+
+ <description>Client integration test - JERSEY-2421 - MultiPartFeature requires jersey-server to be on the class-path</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
new file mode 100644
index 0000000..dc71185
--- /dev/null
+++ b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2421;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.MultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.message.internal.NullOutputStream;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2421.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2421Test {
+
+ private static class TestConnector implements Connector, ConnectorProvider {
+
+ @Override
+ public ClientResponse apply(final ClientRequest request) {
+ try {
+ request.setStreamProvider(new OutboundMessageContext.StreamProvider() {
+ @Override
+ public OutputStream getOutputStream(final int contentLength) throws IOException {
+ return new NullOutputStream();
+ }
+ });
+ request.writeEntity();
+
+ if (request.getHeaderString("Content-Type").contains("boundary")) {
+ return new ClientResponse(Response.Status.OK, request);
+ }
+ } catch (final IOException ioe) {
+ // NOOP
+ }
+ return new ClientResponse(Response.Status.BAD_REQUEST, request);
+ }
+
+ @Override
+ public Future<?> apply(final ClientRequest request, final AsyncConnectorCallback callback) {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public Connector getConnector(final Client client, final Configuration runtimeConfig) {
+ return this;
+ }
+ }
+
+ /**
+ * Test that multipart feature works on the client-side - custom connector checks presence of {@code boundary} parameter in
+ * the {@code Content-Type} header (the header is added to the request in MBW).
+ */
+ @Test
+ public void testMultiPartFeatureOnClient() throws Exception {
+ final Client client = ClientBuilder.newClient(new ClientConfig().connectorProvider(new TestConnector()))
+ .register(MultiPartFeature.class);
+
+ final MultiPart entity = new FormDataMultiPart()
+ .bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("part").build(), "CONTENT"));
+
+ final Response response = client.target("http://localhost").request()
+ .post(Entity.entity(entity, MediaType.MULTIPART_FORM_DATA_TYPE));
+
+ assertThat(response.getStatus(), is(200));
+ }
+
+ /**
+ * Test that classes from jersey-server module cannot be loaded.
+ */
+ @Test(expected = ClassNotFoundException.class)
+ public void testLoadJerseyServerClass() throws Exception {
+ Class.forName("org.glassfish.jersey.server.ResourceConfig");
+ }
+}
diff --git a/tests/integration/jersey-2551/pom.xml b/tests/integration/jersey-2551/pom.xml
new file mode 100644
index 0000000..c3fd8fa
--- /dev/null
+++ b/tests/integration/jersey-2551/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2551</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2551</name>
+
+ <description>Servlet integration test - JERSEY-2551 - Injections#generator field is hard coded to ServiceLocatorGeneratorImpl</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551.java b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551.java
new file mode 100644
index 0000000..13f3277
--- /dev/null
+++ b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2551;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2551 reproducer test.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2551 extends ResourceConfig {
+
+ public Jersey2551() {
+ register(Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Resource.java b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Resource.java
new file mode 100644
index 0000000..04dbe89
--- /dev/null
+++ b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/Resource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2551;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+
+import org.glassfish.hk2.api.ServiceLocator;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class Resource {
+
+ @Inject
+ private ServiceLocator locator;
+
+ @GET
+ public Response get() {
+ return locator instanceof ServiceLocatorGenerator.CustomServiceLocator
+ ? Response.ok().build() : Response.serverError().build();
+ }
+}
diff --git a/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/ServiceLocatorGenerator.java b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/ServiceLocatorGenerator.java
new file mode 100644
index 0000000..610ba43
--- /dev/null
+++ b/tests/integration/jersey-2551/src/main/java/org/glassfish/jersey/tests/integration/jersey2551/ServiceLocatorGenerator.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2551;
+
+import javax.inject.Singleton;
+
+import org.glassfish.hk2.api.DynamicConfigurationService;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.utilities.BuilderHelper;
+
+import org.jvnet.hk2.external.generator.ServiceLocatorGeneratorImpl;
+import org.jvnet.hk2.internal.DefaultClassAnalyzer;
+import org.jvnet.hk2.internal.DynamicConfigurationImpl;
+import org.jvnet.hk2.internal.DynamicConfigurationServiceImpl;
+import org.jvnet.hk2.internal.ServiceLocatorImpl;
+import org.jvnet.hk2.internal.Utilities;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ServiceLocatorGenerator extends ServiceLocatorGeneratorImpl {
+
+ @Override
+ public ServiceLocator create(final String name, final ServiceLocator parent) {
+ if (parent != null && !(parent instanceof ServiceLocatorImpl)) {
+ throw new AssertionError("parent must be a " + ServiceLocatorImpl.class.getName()
+ + " instead it is a " + parent.getClass().getName());
+ }
+
+ final ServiceLocatorImpl sli = new CustomServiceLocator(name, (ServiceLocatorImpl) parent);
+
+ final DynamicConfigurationImpl dci = new DynamicConfigurationImpl(sli);
+
+ // The service locator itself
+ dci.bind(Utilities.getLocatorDescriptor(sli));
+
+ // The injection resolver for three thirty
+ dci.addActiveDescriptor(Utilities.getThreeThirtyDescriptor(sli));
+
+ // The dynamic configuration utility
+ dci.bind(BuilderHelper.link(DynamicConfigurationServiceImpl.class, false)
+ .to(DynamicConfigurationService.class)
+ .in(Singleton.class.getName())
+ .localOnly()
+ .build());
+
+ dci.bind(BuilderHelper.createConstantDescriptor(
+ new DefaultClassAnalyzer(sli)));
+
+ dci.commit();
+
+ return sli;
+ }
+
+ class CustomServiceLocator extends ServiceLocatorImpl {
+
+ public CustomServiceLocator(final String name, final ServiceLocatorImpl parent) {
+ super(name, parent);
+ }
+ }
+}
diff --git a/tests/integration/jersey-2551/src/main/resources/META-INF/services/org.glassfish.hk2.extension.ServiceLocatorGenerator b/tests/integration/jersey-2551/src/main/resources/META-INF/services/org.glassfish.hk2.extension.ServiceLocatorGenerator
new file mode 100644
index 0000000..ad70f6f
--- /dev/null
+++ b/tests/integration/jersey-2551/src/main/resources/META-INF/services/org.glassfish.hk2.extension.ServiceLocatorGenerator
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.jersey2551.ServiceLocatorGenerator
\ No newline at end of file
diff --git a/tests/integration/jersey-2551/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2551/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ea1bd52
--- /dev/null
+++ b/tests/integration/jersey-2551/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2551Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2551.Jersey2551</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2551Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2551/src/test/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551ITCase.java b/tests/integration/jersey-2551/src/test/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551ITCase.java
new file mode 100644
index 0000000..a45e1b4
--- /dev/null
+++ b/tests/integration/jersey-2551/src/test/java/org/glassfish/jersey/tests/integration/jersey2551/Jersey2551ITCase.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2551;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2551.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2551ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2551();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testServiceLocatorServer() throws Exception {
+ assertThat(target().request().get().getStatus(), is(200));
+ }
+}
diff --git a/tests/integration/jersey-2612/pom.xml b/tests/integration/jersey-2612/pom.xml
new file mode 100644
index 0000000..6fe55ac
--- /dev/null
+++ b/tests/integration/jersey-2612/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2612</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2612</name>
+
+ <description>Servlet integration test - JERSEY-2612 - SingleValueExtractor makes it impossible to support java.util.Optional (or Guava Optional).</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612.java b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612.java
new file mode 100644
index 0000000..edb6796
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2612 reproducer test.
+ */
+public class Jersey2612 extends ResourceConfig {
+
+ public Jersey2612() {
+ register(Resource.class);
+ register(OptionalParamFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamBinder.java b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamBinder.java
new file mode 100644
index 0000000..a8808f6
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamBinder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+
+final class OptionalParamBinder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ // Param converter providers
+ bind(OptionalParamConverterProvider.class).to(ParamConverterProvider.class).in(Singleton.class);
+ }
+}
diff --git a/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamConverterProvider.java b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamConverterProvider.java
new file mode 100644
index 0000000..25b6edf
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamConverterProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.internal.util.collection.ClassTypePair;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+
+@Singleton
+public class OptionalParamConverterProvider implements ParamConverterProvider {
+
+ private final InjectionManager injectionManager;
+
+ @Inject
+ public OptionalParamConverterProvider(final InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ }
+
+ @Override
+ public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType, final Annotation[] annotations) {
+ final List<ClassTypePair> ctps = ReflectionHelper.getTypeArgumentAndClass(genericType);
+ final ClassTypePair ctp = (ctps.size() == 1) ? ctps.get(0) : null;
+ if (ctp == null || ctp.rawClass() == String.class) {
+ return new ParamConverter<T>() {
+ @Override
+ public T fromString(final String value) {
+ return rawType.cast(Optional.fromNullable(value));
+ }
+
+ @Override
+ public String toString(final T value) throws IllegalArgumentException {
+ return value.toString();
+ }
+ };
+ }
+ final Set<ParamConverterProvider> converterProviders =
+ Providers.getProviders(injectionManager, ParamConverterProvider.class);
+ for (ParamConverterProvider provider : converterProviders) {
+ @SuppressWarnings("unchecked")
+ final ParamConverter<?> converter = provider.getConverter(ctp.rawClass(), ctp.type(), annotations);
+ if (converter != null) {
+ return new ParamConverter<T>() {
+ @Override
+ public T fromString(final String value) {
+ return rawType.cast(Optional.fromNullable(value)
+ .transform((Function<String, Object>) s -> converter.fromString(value)));
+ }
+
+ @Override
+ public String toString(final T value) throws IllegalArgumentException {
+ return value.toString();
+ }
+ };
+ }
+ }
+ return null;
+ }
+}
diff --git a/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamFeature.java b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamFeature.java
new file mode 100644
index 0000000..d6af4d1
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/OptionalParamFeature.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+public class OptionalParamFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(new OptionalParamBinder());
+ return true;
+ }
+
+}
+
diff --git a/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Resource.java b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Resource.java
new file mode 100644
index 0000000..ad1be27
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/java/org/glassfish/jersey/tests/integration/jersey2612/Resource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+
+/**
+ * Test resource.
+ */
+@Path("/")
+public class Resource {
+
+ @Path("hello")
+ @GET
+ @Produces("text/plain")
+ public String hello(@QueryParam("name") final Optional<String> name) {
+ return "Hello " + name.or("World") + "!";
+ }
+
+ @Path("square")
+ @GET
+ @Produces("text/plain")
+ public int echo(@QueryParam("value") final Optional<Integer> value) {
+ return value.transform(new Function<Integer, Integer>() {
+ @Override
+ public Integer apply(final Integer integer) {
+ return integer * integer;
+ }
+ }).or(0);
+ }
+
+}
diff --git a/tests/integration/jersey-2612/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2612/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f506807
--- /dev/null
+++ b/tests/integration/jersey-2612/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey2612Servlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2612.Jersey2612</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey2612Servlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2612/src/test/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612ITCase.java b/tests/integration/jersey-2612/src/test/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612ITCase.java
new file mode 100644
index 0000000..0ffbad5
--- /dev/null
+++ b/tests/integration/jersey-2612/src/test/java/org/glassfish/jersey/tests/integration/jersey2612/Jersey2612ITCase.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2612;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2612.
+ */
+public class Jersey2612ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2612();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceMethodWithOptionalGivenNoQueryParam() throws Exception {
+ final Response response = target("/hello").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("Hello World!"));
+ }
+
+ @Test
+ public void testResourceMethodWithOptionalGivenQueryParam() throws Exception {
+ final Response response = target("/hello").queryParam("name", "Jersey").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("Hello Jersey!"));
+ }
+
+ @Test
+ public void testResourceMethodWithOptionalIntGivenNoQueryParam() throws Exception {
+ final Response response = target("/square").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("0"));
+ }
+
+ @Test
+ public void testResourceMethodWithOptionalIntGivenQueryParam() throws Exception {
+ final Response response = target("/square").queryParam("value", "42").request().get();
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is("1764"));
+ }
+}
diff --git a/tests/integration/jersey-2637/pom.xml b/tests/integration/jersey-2637/pom.xml
new file mode 100644
index 0000000..8615792
--- /dev/null
+++ b/tests/integration/jersey-2637/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2637</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2637</name>
+
+ <description>
+ Servlet integration test - JERSEY-2637 - sensitive params can be exposed in logs even for POST requests.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637.java b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637.java
new file mode 100644
index 0000000..5f216ee
--- /dev/null
+++ b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2637;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS application for the JERSEY-2637 reproducer test.
+ */
+public class Jersey2637 extends ResourceConfig {
+
+ public Jersey2637() {
+ register(Resource.class);
+ }
+}
diff --git a/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/ParamEatingFilter.java b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/ParamEatingFilter.java
new file mode 100644
index 0000000..d1522c6
--- /dev/null
+++ b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/ParamEatingFilter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2637;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ParamEatingFilter implements Filter {
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ // NOOP
+ }
+
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+ throws IOException, ServletException {
+ // NOM-NOM.
+ request.getParameterMap();
+
+ // Continue.
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ // NOOP
+ }
+}
diff --git a/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Resource.java b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Resource.java
new file mode 100644
index 0000000..39401cf
--- /dev/null
+++ b/tests/integration/jersey-2637/src/main/java/org/glassfish/jersey/tests/integration/jersey2637/Resource.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2637;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+/**
+ * Test resource.
+ */
+@Path("/")
+public class Resource {
+
+ @POST
+ public String params(@FormParam("username") @DefaultValue("ko") final String username,
+ @FormParam("password") @DefaultValue("ko") final String password) {
+ return username + "_" + password;
+ }
+}
diff --git a/tests/integration/jersey-2637/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2637/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..051d43b
--- /dev/null
+++ b/tests/integration/jersey-2637/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>jersey2637Filter</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.jersey2637.ParamEatingFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>jersey2637Filter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2637.Jersey2637</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/default/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>enabled</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2637.Jersey2637</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.form.queryParams.disabled</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>enabled</servlet-name>
+ <url-pattern>/enabled/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>disabled</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2637.Jersey2637</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.form.queryParams.disabled</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>disabled</servlet-name>
+ <url-pattern>/disabled/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637DisabledITCase.java b/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637DisabledITCase.java
new file mode 100644
index 0000000..de6b68e
--- /dev/null
+++ b/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637DisabledITCase.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2637;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2637 - Query params cannot be injected using {@link javax.ws.rs.FormParam}.
+ */
+public class Jersey2637DisabledITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Jersey2637();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testFormParams() throws Exception {
+ final Form form = new Form()
+ .param("username", "user")
+ .param("password", "pass");
+
+ final Response response = target("disabled").request().post(Entity.form(form));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+
+ @Test
+ public void testQueryParams() throws Exception {
+ final Response response = target("disabled")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("ko_ko"));
+ }
+
+ @Test
+ public void testDoubleQueryParams() throws Exception {
+ final Response response = target("disabled")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("ko_ko"));
+ }
+
+ @Test
+ public void testEncodedQueryParams() throws Exception {
+ final Response response = target("disabled")
+ .queryParam("username", "us%20er").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("ko_ko"));
+ }
+
+ @Test
+ public void testFormAndQueryParams() throws Exception {
+ final Form form = new Form()
+ .param("username", "user")
+ .param("password", "pass");
+
+ final Response response = target("disabled")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(form));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+
+ @Test
+ public void testFormAndDoubleQueryParams() throws Exception {
+ final Form form = new Form()
+ .param("username", "user")
+ .param("password", "pass");
+
+ final Response response = target("disabled")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(form));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+}
diff --git a/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637EnabledITCase.java b/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637EnabledITCase.java
new file mode 100644
index 0000000..1240bc1
--- /dev/null
+++ b/tests/integration/jersey-2637/src/test/java/org/glassfish/jersey/tests/integration/jersey2637/Jersey2637EnabledITCase.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2637;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Reproducer tests for JERSEY-2637 - Query params can be injected using {@link javax.ws.rs.FormParam}.
+ */
+@RunWith(Parameterized.class)
+public class Jersey2637EnabledITCase extends JerseyTest {
+
+ @Parameterized.Parameters(name = "path = {0}")
+ public static Collection<Object[]> paths() {
+ return Arrays.asList(new Object[][]{{"defaut"}, {"enabled"}});
+ }
+
+ @Parameterized.Parameter
+ public String path;
+
+ @Override
+ protected Application configure() {
+ return new Jersey2637();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testFormParams() throws Exception {
+ final Form form = new Form()
+ .param("username", "user")
+ .param("password", "pass");
+
+ final Response response = target(path).request().post(Entity.form(form));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+
+ @Test
+ public void testQueryParams() throws Exception {
+ final Response response = target(path)
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+
+ @Test
+ public void testDoubleQueryParams() throws Exception {
+ final Response response = target(path)
+ .queryParam("username", "user").queryParam("password", "pass")
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+
+ @Test
+ public void testEncodedQueryParams() throws Exception {
+ final Response response = target(path)
+ .queryParam("username", "us%20er").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(new Form()));
+
+ assertThat(response.readEntity(String.class), is("us er_pass"));
+ }
+
+ @Test
+ public void testFormAndQueryParams() throws Exception {
+ final Form form = new Form()
+ .param("username", "user")
+ .param("password", "pass");
+
+ final Response response = target(path)
+ .queryParam("username", "user").queryParam("password", "pass")
+ .request()
+ .post(Entity.form(form));
+
+ assertThat(response.readEntity(String.class), is("user_pass"));
+ }
+}
diff --git a/tests/integration/jersey-2654/pom.xml b/tests/integration/jersey-2654/pom.xml
new file mode 100644
index 0000000..7ae7658
--- /dev/null
+++ b/tests/integration/jersey-2654/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2654</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2654</name>
+
+ <description>Jersey test web application - servlet/filter, JERSEY-2654 reproducer</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/ServletFilterTestResource.java b/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/ServletFilterTestResource.java
new file mode 100644
index 0000000..bfc062b
--- /dev/null
+++ b/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/ServletFilterTestResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2654;
+
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+/**
+ * Test resource to be called within an ServletContainer registered as servlet filter.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("filter")
+public class ServletFilterTestResource {
+
+ @GET
+ public Response whatYouSendIsWhatYouGet(@DefaultValue("") @QueryParam("json") final String json) {
+ return Response.ok().entity(json).build();
+ }
+}
diff --git a/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/TestApplication.java b/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/TestApplication.java
new file mode 100644
index 0000000..099008f
--- /dev/null
+++ b/tests/integration/jersey-2654/src/main/java/org/glassfish/jersey/tests/integration/jersey2654/TestApplication.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2654;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application to configure resources for JERSEY-2525 reproducer.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<>();
+ classes.add(ServletFilterTestResource.class);
+ return classes;
+ }
+}
diff --git a/tests/integration/jersey-2654/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2654/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..a75c20f
--- /dev/null
+++ b/tests/integration/jersey-2654/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <filter>
+ <filter-name>MyApplication</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2654.TestApplication</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>MyApplication</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
+
+
diff --git a/tests/integration/jersey-2654/src/test/java/org/glassfish/jersey/tests/integration/jersey2654/Jersey2654ITCase.java b/tests/integration/jersey-2654/src/test/java/org/glassfish/jersey/tests/integration/jersey2654/Jersey2654ITCase.java
new file mode 100644
index 0000000..0589b64
--- /dev/null
+++ b/tests/integration/jersey-2654/src/test/java/org/glassfish/jersey/tests/integration/jersey2654/Jersey2654ITCase.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2654;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Socket;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reproducer for JERSEY-2654
+ *
+ * Tests, that unencoded curly brackets (typically used in URI queries containing JSON) do not cause the request to
+ * fail when running in a servlet environment and configured as a filter.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class Jersey2654ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testJsonInUriWithSockets() throws IOException {
+ // Low level approach with sockets is used, because common Java HTTP clients are using java.net.URI,
+ // which fails when unencoded curly bracket is part of the URI
+ final Socket socket = new Socket(getBaseUri().getHost(), getBaseUri().getPort());
+ final PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
+
+ // quotes are encoded by browsers, curly brackets are not, so the quotes will be sent pre-encoded
+ // HTTP 1.0 is used for simplicity
+ pw.println("GET /filter?json={%22foo%22:%22bar%22} HTTP/1.0");
+ pw.println(); // http request should end with a blank line
+ pw.flush();
+
+ final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ String lastLine = null;
+ String line;
+ while ((line = br.readLine()) != null) {
+ // read the response and remember the last line
+ lastLine = line;
+ }
+ assertEquals("{\"foo\":\"bar\"}", lastLine);
+ br.close();
+ }
+}
diff --git a/tests/integration/jersey-2673/pom.xml b/tests/integration/jersey-2673/pom.xml
new file mode 100644
index 0000000..827aa30
--- /dev/null
+++ b/tests/integration/jersey-2673/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2673</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2673</name>
+
+ <description>Jersey test web application - servlet/filter, JERSEY-2673 reproducer</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673.java b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673.java
new file mode 100644
index 0000000..26f6274
--- /dev/null
+++ b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2673;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * @author Michal Gajdos
+ */
+public class Jersey2673 extends ResourceConfig {
+
+ public Jersey2673() {
+ // Resources.
+ register(Resource.class);
+
+ // Providers.
+ register(JacksonFeature.class);
+
+ // Make sure validations errors are returned to the client.
+ property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
+ }
+}
diff --git a/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Resource.java b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Resource.java
new file mode 100644
index 0000000..326a39e
--- /dev/null
+++ b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/Resource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2673;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import javax.validation.Valid;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+@Produces("application/json")
+public class Resource {
+
+ @POST
+ @Valid
+ public Response processBean(@Valid final SampleBean bean) {
+ return Response.ok(new SampleBean()).build();
+ }
+}
diff --git a/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/SampleBean.java b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/SampleBean.java
new file mode 100644
index 0000000..21ac029
--- /dev/null
+++ b/tests/integration/jersey-2673/src/main/java/org/glassfish/jersey/tests/integration/jersey2673/SampleBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2673;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+/**
+ * @author Michal Gajdos
+ */
+public class SampleBean {
+
+ @NotEmpty
+ private byte[] array;
+
+ public byte[] getArray() {
+ return array;
+ }
+
+ public void setArray(final byte[] array) {
+ this.array = array;
+ }
+}
diff --git a/tests/integration/jersey-2673/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2673/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..712879e
--- /dev/null
+++ b/tests/integration/jersey-2673/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>jersey</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2673.Jersey2673</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jersey</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/tests/integration/jersey-2673/src/test/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673ITCase.java b/tests/integration/jersey-2673/src/test/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673ITCase.java
new file mode 100644
index 0000000..f157001
--- /dev/null
+++ b/tests/integration/jersey-2673/src/test/java/org/glassfish/jersey/tests/integration/jersey2673/Jersey2673ITCase.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2673;
+
+import java.util.List;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.validation.ValidationError;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Reproducer for JERSEY-2673: 400 errors generated by a ValidationException are returning default error page instead of
+ * the Bean Validation's response entity.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2673ITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new Jersey2673();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInputParams() throws Exception {
+ final Response response = target().request("application/json").post(Entity.json(new SampleBean()));
+
+ assertThat(response.getStatusInfo().getStatusCode(), is(Response.Status.BAD_REQUEST.getStatusCode()));
+ assertThat(response.readEntity(new GenericType<List<ValidationError>>() {}).size(), is(1));
+ }
+
+ @Test
+ public void testOutputParams() throws Exception {
+ final SampleBean entity = new SampleBean();
+ entity.setArray(new byte[] {42});
+ final Response response = target().request("application/json").post(Entity.json(entity));
+
+ assertThat(response.getStatusInfo().getStatusCode(), is(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()));
+ assertThat(response.readEntity(new GenericType<List<ValidationError>>() {}).size(), is(1));
+ }
+
+}
diff --git a/tests/integration/jersey-2689/pom.xml b/tests/integration/jersey-2689/pom.xml
new file mode 100644
index 0000000..c4583c8
--- /dev/null
+++ b/tests/integration/jersey-2689/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2689</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2689</name>
+
+ <description>Servlet integration test - JERSEY-2689 - Problem with validation errors on primitive type arrays</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689.java b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689.java
new file mode 100644
index 0000000..fc18355
--- /dev/null
+++ b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2689;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+
+/**
+ * @author Oscar Guindzberg
+ */
+public class Jersey2689 extends ResourceConfig {
+
+ public Jersey2689() {
+ // Set package to look for resources in
+ packages("org.glassfish.jersey.tests.integration.jersey2689");
+
+ this.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
+
+ // create custom ObjectMapper
+ final ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+ // create JsonProvider to provide custom ObjectMapper
+ final JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
+ provider.setMapper(mapper);
+ this.register(provider);
+
+ }
+
+}
diff --git a/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Resource.java b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Resource.java
new file mode 100644
index 0000000..6e97b9e
--- /dev/null
+++ b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2689;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import javax.validation.Valid;
+
+@Path("/")
+public class Resource {
+
+ @POST
+ @Path("/post-bean")
+ public void processBean(@Valid final SampleBean bean) {
+ //do-nothing
+ }
+}
diff --git a/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/SampleBean.java b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/SampleBean.java
new file mode 100644
index 0000000..a4e759d
--- /dev/null
+++ b/tests/integration/jersey-2689/src/main/java/org/glassfish/jersey/tests/integration/jersey2689/SampleBean.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2689;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+public class SampleBean {
+
+ @NotEmpty
+ private byte[] array;
+
+ public byte[] getArray() {
+ return array;
+ }
+
+ public void setArray(byte[] array) {
+ this.array = array;
+ }
+
+}
diff --git a/tests/integration/jersey-2689/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2689/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3842845
--- /dev/null
+++ b/tests/integration/jersey-2689/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2689.Jersey2689</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/tests/integration/jersey-2689/src/test/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689ITCase.java b/tests/integration/jersey-2689/src/test/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689ITCase.java
new file mode 100644
index 0000000..2db2efa
--- /dev/null
+++ b/tests/integration/jersey-2689/src/test/java/org/glassfish/jersey/tests/integration/jersey2689/Jersey2689ITCase.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2689;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+
+/**
+ * Tests for JERSEY-2689: Problem with validation errors on primitive type arrays.
+ * <p/> There is a bug when a validation fails for a primitive data array. Eg a NotNull failed validation on a byte[] causes the code to throw a ClassCastException. The problem is caused by ValidationHelper.getViolationInvalidValue(Object invalidValue) It tries to cast any array to a Object[] A byte[] parameter would generate a ClassCastException.*
+ * @author Oscar Guindzberg (oscar.guindzberg at gmail.com)
+ */
+public class Jersey2689ITCase extends JerseyTest {
+
+
+ @Override
+ protected ResourceConfig configure() {
+ return new Jersey2689();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Checks if a thread gets stuck when an {@code IOException} is thrown from the {@code
+ * MessageBodyWriter#writeTo}.
+ */
+ @Test
+ public void testByteArray() throws Exception {
+ // Executor.
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ final Future<Response> responseFuture = executor.submit(new Callable<Response>() {
+
+ @Override
+ public Response call() throws Exception {
+ SampleBean bean = new SampleBean();
+ bean.setArray(new byte[]{});
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
+ provider.setMapper(mapper);
+ client().register(provider);
+
+ return target().path("post-bean").request().post(Entity.entity(bean, MediaType.APPLICATION_JSON));
+ }
+
+ });
+
+ executor.shutdown();
+ final boolean inTime = executor.awaitTermination(5000, TimeUnit.MILLISECONDS);
+
+ // Asserts.
+ assertTrue(inTime);
+
+ // Response.
+ final Response response = responseFuture.get();
+
+ //Make sure we get a 400 error and not a 500 error
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+ }
+
+
+}
diff --git a/tests/integration/jersey-2704/pom.xml b/tests/integration/jersey-2704/pom.xml
new file mode 100644
index 0000000..5dea360
--- /dev/null
+++ b/tests/integration/jersey-2704/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2704</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2704</name>
+
+ <description>
+ This test is to verify if ServiceLocator can be configured within the server context
+ in such a way that Jersey can use it as a parent ServiceLocator in the WebComponent.
+ More details can be found in JERSEY-2704.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/ServiceLocatorSetup.java b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/ServiceLocatorSetup.java
new file mode 100644
index 0000000..3eb8be8
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/ServiceLocatorSetup.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.tests.integration.jersey2704.services.HappyService;
+
+
+/**
+ * This class is to listen for {@link ServletContextEvent} generated whenever context
+ * is initialized and set {@link ServletProperties#SERVICE_LOCATOR} attribute to point
+ * {@link ServiceLocator} pre-populated with {@link HappyService} instance.
+ *
+ * @author Bartosz Firyn (sarxos)
+ */
+public class ServiceLocatorSetup implements ServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent event) {
+ ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
+ ServiceLocatorUtilities.addOneConstant(locator, new HappyService());
+ event.getServletContext().setAttribute(ServletProperties.SERVICE_LOCATOR, locator);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent event) {
+ }
+}
diff --git a/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestApplication.java b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestApplication.java
new file mode 100644
index 0000000..ac7bc57
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+
+/**
+ * Jersey application.
+ *
+ * @author Bartosz Firyn (bartoszfiryn at gmail.com)
+ */
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ }
+}
diff --git a/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestResource.java b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestResource.java
new file mode 100644
index 0000000..dc07f94
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/TestResource.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+/**
+ * This resource is used to test if specific service class instance is available in the
+ * {@link InjectionManager} that comes from Jersey context.
+ *
+ * @author Bartosz Firyn (bartoszfiryn at gmail.com)
+ */
+@Path("test")
+public class TestResource {
+
+ InjectionManager injectionManager;
+
+ /**
+ * Inject {@link InjectionManager} from Jersey context.
+ *
+ * @param injectionManager the {@link InjectionManager}
+ */
+ @Inject
+ public TestResource(InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ }
+
+ /**
+ * This method will test given class by checking if it is available in {@link InjectionManager}
+ * that has been injected from the Jersey context.
+ *
+ * @param clazz the service class name to check
+ * @return {@link Response} with status code 200 if service is available, 600 otherwise
+ * @throws Exception in case when there are any error (e.g. class not exist)
+ */
+ @GET
+ @Path("{clazz}")
+ @Produces("text/plain")
+ public Response test(@PathParam("clazz") String clazz) throws Exception {
+ return Response
+ .status(injectionManager.getInstance(Class.forName(clazz)) != null ? 200 : 600)
+ .build();
+ }
+}
diff --git a/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/HappyService.java b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/HappyService.java
new file mode 100644
index 0000000..2c87d94
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/HappyService.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704.services;
+
+import org.jvnet.hk2.annotations.Service;
+
+
+/**
+ * This service is registered in the {@link org.glassfish.jersey.internal.inject.InjectionManager} and therefore
+ * can be used in Jersey resources.
+ *
+ * @author Bartosz Firyn (bartoszfiryn at gmail.com)
+ */
+@Service
+public class HappyService {
+
+}
diff --git a/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/SadService.java b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/SadService.java
new file mode 100644
index 0000000..1d4df28
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/java/org/glassfish/jersey/tests/integration/jersey2704/services/SadService.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704.services;
+
+import org.jvnet.hk2.annotations.Service;
+
+
+/**
+ * This service is not registered in {@link org.glassfish.jersey.internal.inject.InjectionManager} and therefore cannot
+ * be used in the Jersey resources.
+ *
+ * @author Bartosz Firyn (bartoszfiryn at gmail.com)
+ */
+@Service
+public class SadService {
+
+}
diff --git a/tests/integration/jersey-2704/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2704/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..44a2543
--- /dev/null
+++ b/tests/integration/jersey-2704/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <listener>
+ <listener-class>org.glassfish.jersey.tests.integration.jersey2704.ServiceLocatorSetup</listener-class>
+ </listener>
+ <servlet>
+ <servlet-name>test</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2704.TestApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>test</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-2704/src/test/java/org/glassfish/jersey/tests/integration/jersey2704/Jersey2704ITCase.java b/tests/integration/jersey-2704/src/test/java/org/glassfish/jersey/tests/integration/jersey2704/Jersey2704ITCase.java
new file mode 100644
index 0000000..2ed829e
--- /dev/null
+++ b/tests/integration/jersey-2704/src/test/java/org/glassfish/jersey/tests/integration/jersey2704/Jersey2704ITCase.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2704;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.jersey2704.services.HappyService;
+import org.glassfish.jersey.tests.integration.jersey2704.services.SadService;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/**
+ * This test case is to cover enhancement implemented in JERSEY-2704. The goal of this enhancement
+ * is to give users possibility to register main {@link ServiceLocator} in the servlet context, so
+ * it can be later used by Jersey. This creates the opportunity to wire Jersey-specific classes with
+ * the services created outside the Jersey context.
+ *
+ * @author Bartosz Firyn (bartoszfiryn at gmail.com)
+ */
+public class Jersey2704ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Invokes REST endpoint to check whether specific class service is registered in the
+ * {@link ServiceLocator}.
+ *
+ * @param service the service class
+ * @return HTTP status code, 200 when service is available and 600 otherwise
+ * @throws IOException in case of problems with HTTP communication
+ */
+ private int test(Class<?> service) throws IOException {
+
+ String name = service.getCanonicalName();
+ String path = getBaseUri().toString() + "test/" + name;
+
+ HttpURLConnection connection = (HttpURLConnection) new URL(path).openConnection();
+ connection.setRequestMethod("GET");
+ connection.connect();
+ connection.disconnect();
+
+ return connection.getResponseCode();
+ }
+
+ /**
+ * Test to cover sunny day scenario, i.e. specific service has been registered in the parent
+ * {@link ServiceLocator} so it will be available in the one that is used in Jersey context.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testCorrectInjection() throws IOException {
+ Assert.assertEquals(200, test(HappyService.class));
+ }
+
+ /**
+ * Test to cover rainy day scenario, i.e. specific service has <b>not</b> been registered in the
+ * parent {@link ServiceLocator} so it cannot be used to wire Jersey classes.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testMisingInjection() throws IOException {
+ Assert.assertEquals(600, test(SadService.class));
+ }
+}
diff --git a/tests/integration/jersey-2776/pom.xml b/tests/integration/jersey-2776/pom.xml
new file mode 100644
index 0000000..0b484a9
--- /dev/null
+++ b/tests/integration/jersey-2776/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2776</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2776</name>
+
+ <description>
+ This test is to verify that multipart support (server side) works even if apache CXF's RuntimeDelegateImpl is used instead
+ of the RuntimeDelegateImpl shipped with Jersey.
+ </description>
+
+ <dependencies>
+ <!-- For testing multipart support with another http client -->
+ <!-- The order of these imports are important as it's the first dependency that has a javax.ws.rs.ext.RuntimeDelegate in
+ the services that will be used. -->
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-client</artifactId>
+ <version>3.0.3</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestApplication.java b/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestApplication.java
new file mode 100644
index 0000000..3739ba3
--- /dev/null
+++ b/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestApplication.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2776;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application.
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ register(MultiPartFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestResource.java b/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestResource.java
new file mode 100644
index 0000000..1f05e91
--- /dev/null
+++ b/tests/integration/jersey-2776/src/main/java/org/glassfish/jersey/tests/integration/jersey2776/TestResource.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2776;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+@Path("/files")
+public class TestResource {
+
+ @POST
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadDocument(@FormDataParam("file_path") final FormDataBodyPart body) {
+ return body.getValueAs(String.class);
+ }
+}
diff --git a/tests/integration/jersey-2776/src/test/java/org/glassfish/jersey/tests/integration/jersey2776/Jersey2776ITCase.java b/tests/integration/jersey-2776/src/test/java/org/glassfish/jersey/tests/integration/jersey2776/Jersey2776ITCase.java
new file mode 100644
index 0000000..7a6d2af
--- /dev/null
+++ b/tests/integration/jersey-2776/src/test/java/org/glassfish/jersey/tests/integration/jersey2776/Jersey2776ITCase.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2776;
+
+import java.nio.charset.StandardCharsets;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.AttachmentBuilder;
+import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Code under test: {@link MultiPartReaderClientSide} (unquoteMediaTypeParameters)
+ *
+ * @author Jonatan Jönsson (jontejj at gmail.com)
+ */
+@Ignore
+public class Jersey2776ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Path("/files")
+ public interface ApacheCxfMultipartClient {
+
+ @POST
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.TEXT_PLAIN)
+ String uploadDocument(MultipartBody content);
+ }
+
+ @Test
+ public void testThatMultipartServerSupportsBoundaryQuotesEvenWithInterferingRuntimeDelegate() {
+ final JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+ bean.setAddress(getBaseUri().toString());
+ bean.setServiceClass(ApacheCxfMultipartClient.class);
+ final ApacheCxfMultipartClient cxfClient = bean.create(ApacheCxfMultipartClient.class);
+
+ final String originalContent = "abc";
+ final byte[] content = originalContent.getBytes(StandardCharsets.US_ASCII);
+ final Attachment fileAttachment = new AttachmentBuilder()
+ .object(content)
+ .contentDisposition(new ContentDisposition("form-data; filename=\"abc-file\"; name=\"file_path\""))
+ .build();
+
+ final String fileContentReturnedFromServer = cxfClient.uploadDocument(new MultipartBody(fileAttachment));
+ assertThat(fileContentReturnedFromServer, equalTo(originalContent));
+ }
+}
diff --git a/tests/integration/jersey-2794/pom.xml b/tests/integration/jersey-2794/pom.xml
new file mode 100644
index 0000000..f009641
--- /dev/null
+++ b/tests/integration/jersey-2794/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2794</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2794</name>
+
+ <description>
+ Reproducer of JERSEY-2794. This test makes sure that temporary files created via mimepull library are deleted right after
+ the request processing failed and not when the JVM is shut down.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestApplication.java b/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestApplication.java
new file mode 100644
index 0000000..615df07
--- /dev/null
+++ b/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestApplication.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2794;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application for JERSEY-2794.
+ *
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ register(MultiPartFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestResource.java b/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestResource.java
new file mode 100644
index 0000000..aa8b89f
--- /dev/null
+++ b/tests/integration/jersey-2794/src/main/java/org/glassfish/jersey/tests/integration/jersey2794/TestResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2794;
+
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class TestResource {
+
+ @PUT
+ @Consumes("multipart/form-data")
+ @Produces("text/plain")
+ public String put(@FormDataParam("stream") final InputStream stream) {
+ return "OK";
+ }
+}
diff --git a/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
new file mode 100644
index 0000000..60a54ca
--- /dev/null
+++ b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2794;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JERSEY-2794 reproducer.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2794ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void mimeTempFileRemoved() throws Exception {
+ final String tempDir = System.getProperty("java.io.tmpdir");
+
+ // Get number of matching MIME*tmp files (the number should be the same at the end of the test).
+ final int expectedTempFiles = matchingTempFiles(tempDir);
+
+ final URL url = new URL(getBaseUri().toString());
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("PUT");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=XXXX_YYYY");
+
+ connection.setDoOutput(true);
+ connection.connect();
+
+ final OutputStream outputStream = connection.getOutputStream();
+ outputStream.write("--XXXX_YYYY".getBytes());
+ outputStream.write('\n');
+ outputStream.write("Content-Type: text/plain".getBytes());
+ outputStream.write('\n');
+ outputStream.write("Content-Disposition: form-data; name=\"big-part\"".getBytes());
+ outputStream.write('\n');
+ outputStream.write('\n');
+
+ // Send big chunk of data.
+ for (int i = 0; i < 16 * 4096; i++) {
+ outputStream.write('E');
+ if (i % 1024 == 0) {
+ outputStream.flush();
+ }
+ }
+
+ // Do NOT send end of the MultiPart message to simulate the issue.
+
+ // Get Response ...
+ assertThat("Bad Request expected", connection.getResponseCode(), is(400));
+
+ // Make sure that the Mimepull message and it's parts have been closed and temporary files deleted.
+ assertThat("Temporary mimepull files were not deleted", matchingTempFiles(tempDir), is(expectedTempFiles));
+
+ // ... Disconnect.
+ connection.disconnect();
+ }
+
+ private int matchingTempFiles(final String tempDir) throws IOException {
+ AtomicInteger count = new AtomicInteger(0);
+ Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (file.getFileName().startsWith("MIME") && file.getFileName().endsWith("tmp")) {
+ count.incrementAndGet();
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ return count.get();
+ }
+}
diff --git a/tests/integration/jersey-2846/pom.xml b/tests/integration/jersey-2846/pom.xml
new file mode 100644
index 0000000..7e54819
--- /dev/null
+++ b/tests/integration/jersey-2846/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2846</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2846</name>
+
+ <description>
+ Reproducer of JERSEY-2846. This test makes sure that temporary files created via mimepull (and moved by Jersey) library
+ are deleted right after the request processing (either successful or unsuccessful) and not when the JVM is shut down.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestApplication.java b/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestApplication.java
new file mode 100644
index 0000000..42dafbe
--- /dev/null
+++ b/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestApplication.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2846;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application for JERSEY-2846.
+ *
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ register(MultiPartFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestResource.java b/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestResource.java
new file mode 100644
index 0000000..7356fcf
--- /dev/null
+++ b/tests/integration/jersey-2846/src/main/java/org/glassfish/jersey/tests/integration/jersey2846/TestResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2846;
+
+import java.io.File;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+@Consumes("multipart/form-data")
+@Produces("text/plain")
+public class TestResource {
+
+ @POST
+ @Path("ExceptionInMethod")
+ public String exceptionInMethod(@FormDataParam("file") final File file) {
+ throw new WebApplicationException(Response.serverError().entity(file.getAbsolutePath()).build());
+ }
+
+ @POST
+ @Path("SuccessfulMethod")
+ public String successfulMethod(@FormDataParam("file") final File file) {
+ return file.getAbsolutePath();
+ }
+}
diff --git a/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
new file mode 100644
index 0000000..0aecaa2
--- /dev/null
+++ b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2846;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JERSEY-2846 reproducer.
+ *
+ * @author Michal Gajdos
+ */
+public class Jersey2846ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(MultiPartFeature.class);
+ }
+
+ @Test
+ public void tempFileDeletedAfterSuccessfulProcessing() throws Exception {
+ _testSmall("SuccessfulMethod", 200);
+ }
+
+ @Test
+ public void tempFileDeletedAfterExceptionInMethod() throws Exception {
+ _testSmall("ExceptionInMethod", 500);
+ }
+
+ @Test
+ public void tempFileDeletedAfterSuccessfulProcessingBigEntity() throws Exception {
+ _testBig("SuccessfulMethod", 200);
+ }
+
+ @Test
+ public void tempFileDeletedAfterExceptionInMethodBigEntity() throws Exception {
+ _testBig("ExceptionInMethod", 500);
+ }
+
+ public void _testBig(final String path, final int status) throws Exception {
+ final byte[] array = new byte[8196];
+ Arrays.fill(array, (byte) 52);
+
+ _test(path, status, array);
+ }
+
+ public void _testSmall(final String path, final int status) throws Exception {
+ _test(path, status, "CONTENT");
+ }
+
+ public void _test(final String path, final int status, final Object entity) throws Exception {
+ final String tempDir = System.getProperty("java.io.tmpdir");
+
+ // Get number of matching MIME*tmp files (the number should be the same at the end of the test).
+ final int expectedTempFiles = matchingTempFiles(tempDir);
+
+ final FormDataMultiPart multipart = new FormDataMultiPart();
+ final FormDataBodyPart bodypart = new FormDataBodyPart(FormDataContentDisposition.name("file").fileName("file").build(),
+ entity, MediaType.TEXT_PLAIN_TYPE);
+ multipart.bodyPart(bodypart);
+
+ final Response response = target().path(path)
+ .request()
+ .post(Entity.entity(multipart, MediaType.MULTIPART_FORM_DATA));
+
+ // Get Response ...
+ assertThat(response.getStatus(), is(status));
+ // Wait a second to make sure the files don't exist.
+ Thread.sleep(1000);
+
+ // Make sure that the message and it's parts have been closed and temporary files deleted.
+ assertThat("Temporary files were not deleted", matchingTempFiles(tempDir), is(expectedTempFiles));
+ }
+
+ private int matchingTempFiles(final String tempDir) throws IOException {
+ AtomicInteger count = new AtomicInteger(0);
+ Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Path name = file.getFileName();
+ if ((name.startsWith("rep") || name.startsWith("MIME")) && name.endsWith("tmp")) {
+ count.incrementAndGet();
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ return count.get();
+ }
+}
diff --git a/tests/integration/jersey-2878/pom.xml b/tests/integration/jersey-2878/pom.xml
new file mode 100644
index 0000000..2cf6ae1
--- /dev/null
+++ b/tests/integration/jersey-2878/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2878</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2878</name>
+
+ <description>
+ Reproducer of JERSEY-2878.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestApplication.java b/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestApplication.java
new file mode 100644
index 0000000..a7f533e
--- /dev/null
+++ b/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestApplication.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2878;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application for JERSEY-2878.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ }
+}
diff --git a/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestResource.java b/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestResource.java
new file mode 100644
index 0000000..eaada6a
--- /dev/null
+++ b/tests/integration/jersey-2878/src/main/java/org/glassfish/jersey/tests/integration/jersey2878/TestResource.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2878;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * A simple resource that returns a string.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("string")
+public class TestResource {
+
+ @GET
+ public String string() {
+ return "Hello, World! "
+ + "In production this response would be large, "
+ + "and unsuitable for buffering in memory";
+ }
+}
diff --git a/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ApacheITCase.java b/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ApacheITCase.java
new file mode 100644
index 0000000..8786b52
--- /dev/null
+++ b/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ApacheITCase.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2878;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+
+/**
+ * Additional test class that tests jersey client configured with the apache http.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class Jersey2878ApacheITCase extends Jersey2878ITCase {
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.connectorProvider(new ApacheConnectorProvider());
+
+ super.configureClient(config);
+ }
+}
diff --git a/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ITCase.java b/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ITCase.java
new file mode 100644
index 0000000..a31f49f
--- /dev/null
+++ b/tests/integration/jersey-2878/src/test/java/org/glassfish/jersey/tests/integration/jersey2878/Jersey2878ITCase.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2878;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+public class Jersey2878ITCase extends JerseyTest {
+
+ private List<InputStream> responseInputStreams = new ArrayList<>();
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ ClientResponseFilter trackInputStreams = new ClientResponseFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ responseInputStreams.add(responseContext.getEntityStream());
+ }
+ };
+
+ config.register(trackInputStreams);
+ }
+
+ private static void consumeStreamFully(InputStream inputStream) throws IOException {
+ while (inputStream.read() != -1) {
+ //consume the stream fully
+ }
+ }
+
+ @Test
+ public void thisShouldWorkButFails() throws Exception {
+ InputStream stream = target("string").request().get(InputStream.class);
+ try {
+ consumeStreamFully(stream);
+ } finally {
+ stream.close();
+ }
+
+ try {
+ stream.read();
+ fail("Exception was not thrown when read() was called on closed stream! Stream implementation: " + stream.getClass());
+ } catch (IOException e) {
+ // this is desired
+ }
+
+ assertThatAllInputStreamsAreClosed();
+ }
+
+ @Test
+ public void thisWorksButIsReallyUgly() throws Exception {
+ Response response = target("string").request().get();
+ if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
+ throw new RuntimeException("We have to manually check that the response was successful");
+ }
+ InputStream stream = response.readEntity(InputStream.class);
+ try {
+ consumeStreamFully(stream);
+ } finally {
+ response.close();
+ }
+
+ try {
+ stream.read();
+ fail("Exception was not thrown when read() was called on closed stream! Stream implementation: " + stream.getClass());
+ } catch (IOException e) {
+ // this is desired
+ }
+
+ assertThatAllInputStreamsAreClosed();
+ }
+
+ @Test
+ public void thisAlsoFails() throws Exception {
+ Response response = target("string").request().get();
+ if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
+ throw new RuntimeException("We have to manually check that the response was successful");
+ }
+
+ InputStream stream = response.readEntity(InputStream.class);
+ try {
+ consumeStreamFully(stream);
+ } finally {
+ stream.close();
+ }
+
+ try {
+ stream.read();
+ fail("Exception was not thrown when read() was called on closed stream! Stream implementation: " + stream.getClass());
+ } catch (IOException e) {
+ // this is desired
+ }
+
+ assertThatAllInputStreamsAreClosed();
+ }
+
+ @Test
+ public void worksWithACast_ifYouKnowThatYouCanCast() throws Exception {
+ Response response = target("string").request().get();
+ if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
+ throw new RuntimeException("We have to manually check that the response was successful");
+ }
+
+ InputStream stream = (InputStream) response.getEntity();
+ try {
+ consumeStreamFully(stream);
+ } finally {
+ stream.close();
+ }
+
+ try {
+ stream.read();
+ fail("Exception was not thrown when read() was called on closed stream! Stream implementation: " + stream.getClass());
+ } catch (IOException e) {
+ // this is desired
+ }
+
+ assertThatAllInputStreamsAreClosed();
+ }
+
+ private void assertThatAllInputStreamsAreClosed() {
+ if (responseInputStreams.size() == 0) {
+ fail("no input stream to check");
+ }
+ for (InputStream stream : responseInputStreams) {
+ assertClosed(stream);
+ }
+ }
+
+ private void assertClosed(InputStream stream) {
+ try {
+ byte[] buffer = new byte[256];
+ stream.read(buffer); //it's not ignored — we're checking for the exception
+ fail("Stream is not closed! Stream implementation: " + stream.getClass());
+ } catch (IOException e) {
+ // an exception is desired
+ }
+ }
+}
diff --git a/tests/integration/jersey-2892/pom.xml b/tests/integration/jersey-2892/pom.xml
new file mode 100644
index 0000000..1e4647f
--- /dev/null
+++ b/tests/integration/jersey-2892/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-2892</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-2892</name>
+
+ <description>
+ Reproducer of JERSEY-2892.
+
+ Repeating classes in object graph of entity filtering facility should not be always filtered out.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- which jersey media provider to use is determined in web.xml by using 'jersey.config.jsonFeature' init param -->
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestApplication.java b/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestApplication.java
new file mode 100644
index 0000000..f1b5eb0
--- /dev/null
+++ b/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestApplication.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2892;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application for JERSEY-2878 and also J-605 (which is derived from the former one).
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ register(EntityFilteringFeature.class);
+ }
+}
diff --git a/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestResource.java b/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestResource.java
new file mode 100644
index 0000000..c59b252
--- /dev/null
+++ b/tests/integration/jersey-2892/src/main/java/org/glassfish/jersey/tests/integration/jersey2892/TestResource.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2892;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.annotation.XmlTransient;
+
+/**
+ * A resource that provides a means to test whether repeating classes in object graph are correctly filtered out.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/")
+@Produces(MediaType.APPLICATION_JSON)
+public class TestResource {
+
+ @GET
+ @Path("pointer")
+ public Pointer pointer() {
+ return new Pointer();
+ }
+
+ public static class Pointer {
+
+ public final Persons persons = new Persons();
+ }
+
+ @GET
+ @Path("test")
+ public Persons issue() {
+ return new Persons();
+ }
+
+ public static class Persons {
+
+ public final Person first = new Person("Larry", "Amphitheatre Pkwy", 1600, "Mountain View");
+ public final Person second = new Person("Bill", "Microsoft Way", 1, "Redmond");
+ }
+
+ public static class Person {
+
+ public Person() {
+ }
+
+ public Person(final String name, final String streetName, final int streetNumber, final String city) {
+ this.name = name;
+ address = new Address(streetName, streetNumber, city);
+ }
+
+ public Address address;
+ public String name;
+ }
+
+ public static class Address {
+
+ public Address() {
+ }
+
+ public Address(final String name, final int number, final String city) {
+ this.city = city;
+ street = new Street(name, number);
+ }
+
+ public Street street;
+ public String city;
+ }
+
+ public static class Street {
+
+ public Street() {
+ }
+
+ public Street(final String name, final int number) {
+ this.name = name;
+ this.number = number;
+ }
+
+ public String name;
+ public int number;
+ }
+
+ @GET
+ @Path("recursive")
+ public Recursive recursive() {
+ return new Recursive();
+ }
+
+ public static class Recursive {
+
+ public String idRecursive = "a";
+ public SubField subField = new SubField();
+ }
+
+ public static class SubField {
+
+ public final String idSubField = "b";
+ public final SubSubField subSubField;
+
+ public SubField() {
+ subSubField = new SubSubField(this);
+ }
+ }
+
+ public static class SubSubField {
+
+ public final String idSubSubField = "c";
+
+ @XmlTransient
+ public SubField subField;
+
+ public SubSubField() {
+ }
+
+ public SubSubField(final SubField subField) {
+ this.subField = subField;
+ }
+ }
+}
diff --git a/tests/integration/jersey-2892/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-2892/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d52a435
--- /dev/null
+++ b/tests/integration/jersey-2892/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <servlet>
+ <servlet-name>jerseyMoxyFilteringFeature</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2892.TestApplication</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.jsonFeature</param-name>
+ <param-value>MoxyJsonFeature</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jerseyMoxyFilteringFeature</servlet-name>
+ <url-pattern>/moxy/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>jerseyJacksonFilteringFeature</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey2892.TestApplication</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.jsonFeature</param-name>
+ <param-value>JacksonFeature</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jerseyJacksonFilteringFeature</servlet-name>
+ <url-pattern>/jackson/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/AbstractJerseyEntityFilteringITCase.java b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/AbstractJerseyEntityFilteringITCase.java
new file mode 100644
index 0000000..ac5a7ab
--- /dev/null
+++ b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/AbstractJerseyEntityFilteringITCase.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2892;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests whether classes repeating in the object graph are filtered out correctly.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public abstract class AbstractJerseyEntityFilteringITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Tests whether sub-sub-field, {@link TestResource.Street} in particular,
+ * is not filtered out.
+ * <p/>
+ * This corresponds with the JERSEY-2892 reported case.
+ */
+ @Test
+ public void testWhetherSubSubFiledIsNotFilteredOut() {
+ Response response = target(provider() + "/test").request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ final TestResource.Persons persons = response.readEntity(TestResource.Persons.class);
+
+ Assert.assertEquals("Amphitheatre Pkwy", persons.first.address.street.name);
+ Assert.assertEquals("Microsoft Way", persons.second.address.street.name);
+ }
+
+ /**
+ * Tests whether a de-referenced case of the reported problem is still correctly not filtered out. In particular, a
+ * sub-sub-sub-field of the same class is not filtered out.
+ */
+ @Test
+ public void testWhetherSubSubSubFieldIsNotFilteredOut() {
+ Response response = target(provider() + "/pointer").request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ final TestResource.Pointer pointer = response.readEntity(TestResource.Pointer.class);
+
+ Assert.assertEquals("Amphitheatre Pkwy", pointer.persons.first.address.street.name);
+ Assert.assertEquals("Microsoft Way", pointer.persons.second.address.street.name);
+ }
+
+ /**
+ * Tests whether a reference cycle is detected and infinite recursion is prevented.
+ */
+ @Test
+ public void testWhetherReferenceCycleIsDetected() {
+ Response response = target(provider() + "/recursive").request(MediaType.APPLICATION_JSON_TYPE).get();
+
+ final TestResource.Recursive recursive = response.readEntity(TestResource.Recursive.class);
+
+ Assert.assertEquals("c", recursive.subField.subSubField.idSubSubField);
+ }
+
+ /**
+ * Jersey Entity filtering feature provider.
+ *
+ * @return The provider string to match with appropriate Jersey app configured in web.xml.
+ */
+ protected abstract String provider();
+
+}
diff --git a/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/J605MoxyITCase.java b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/J605MoxyITCase.java
new file mode 100644
index 0000000..501df41
--- /dev/null
+++ b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/J605MoxyITCase.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2892;
+
+/**
+ * Tests whether classes repeating in the object graph are filtered out correctly when using MOXY json provider.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class J605MoxyITCase extends AbstractJerseyEntityFilteringITCase {
+
+ @Override
+ protected String provider() {
+ return "moxy";
+ }
+}
diff --git a/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/Jersey2892JacksonITCase.java b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/Jersey2892JacksonITCase.java
new file mode 100644
index 0000000..1ce858e
--- /dev/null
+++ b/tests/integration/jersey-2892/src/test/java/org/glassfish/jersey/tests/integration/jersey2892/Jersey2892JacksonITCase.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey2892;
+
+/**
+ * Tests whether classes repeating in the object graph are filtered out correctly when using Jackson json provider.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class Jersey2892JacksonITCase extends AbstractJerseyEntityFilteringITCase {
+
+ @Override
+ protected String provider() {
+ return "jackson";
+ }
+}
diff --git a/tests/integration/jersey-780/pom.xml b/tests/integration/jersey-780/pom.xml
new file mode 100644
index 0000000..2962171
--- /dev/null
+++ b/tests/integration/jersey-780/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-780</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-780</name>
+
+ <description>Servlet integration test - JERSEY-780 - Malformed URL returns a 500 instead of a 400</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResource.java b/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResource.java
new file mode 100644
index 0000000..9049c36
--- /dev/null
+++ b/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey780;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/Jersey780.java b/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/Jersey780.java
new file mode 100644
index 0000000..5ea850a
--- /dev/null
+++ b/tests/integration/jersey-780/src/main/java/org/glassfish/jersey/tests/integration/jersey780/Jersey780.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey780;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+public class Jersey780 extends Application {
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.<Class<?>>singleton(HelloWorldResource.class);
+ }
+}
diff --git a/tests/integration/jersey-780/src/main/webapp/WEB-INF/web.xml b/tests/integration/jersey-780/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..007d609
--- /dev/null
+++ b/tests/integration/jersey-780/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.jersey780.Jersey780</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/jersey-780/src/test/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResourceITCase.java b/tests/integration/jersey-780/src/test/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..f54d531
--- /dev/null
+++ b/tests/integration/jersey-780/src/test/java/org/glassfish/jersey/tests/integration/jersey780/HelloWorldResourceITCase.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.jersey780;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig().registerInstances(new Jersey780());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInvalidUrl() throws Exception {
+ List<Integer> expectedCodes = Arrays.asList(
+ Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.NOT_FOUND.getStatusCode());
+ List<String> expectedPhrases = Arrays.asList(
+ Response.Status.BAD_REQUEST.getReasonPhrase(), Response.Status.NOT_FOUND.getReasonPhrase());
+
+ final URL url = new URL(getBaseUri().toString() + "^");
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+
+ connection.connect();
+
+ final int statusCode = connection.getResponseCode();
+ final String statusMessage = connection.getResponseMessage();
+
+ connection.disconnect();
+
+ assertTrue("Wrong response status code: " + statusCode,
+ expectedCodes.contains(statusCode));
+ assertTrue("Wrong response status reason: " + statusMessage,
+ expectedPhrases.contains(statusMessage));
+ }
+}
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
new file mode 100644
index 0000000..d28865c
--- /dev/null
+++ b/tests/integration/pom.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-integration</name>
+
+ <modules>
+ <module>async-jersey-filter</module>
+ <module>cdi-beanvalidation-webapp</module>
+ <module>cdi-ejb-test-webapp</module>
+ <module>cdi-iface-with-non-jaxrs-impl-test-webapp</module>
+ <module>cdi-multimodule</module>
+ <module>ejb-multimodule-reload</module>
+ <module>cdi-multipart-webapp</module>
+ <module>cdi-test-webapp</module>
+ <module>cdi-with-jersey-injection-custom-cfg-webapp</module>
+ <module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>
+ <module>cdi-with-jersey-injection-webapp</module>
+ <module>client-connector-provider</module>
+ <module>ejb-multimodule</module>
+ <module>ejb-test-webapp</module>
+ <module>j-376</module>
+ <module>j-441</module>
+ <module>j-59</module>
+ <module>jaxrs-component-inject</module>
+ <module>jersey-1107</module>
+ <module>jersey-1223</module>
+ <module>jersey-1604</module>
+ <module>jersey-1667</module>
+ <module>jersey-1829</module>
+ <module>jersey-1883</module>
+ <module>jersey-1928</module>
+ <module>jersey-1960</module>
+ <module>jersey-1964</module>
+ <module>jersey-2031</module>
+ <module>jersey-2136</module>
+ <module>jersey-2137</module>
+ <module>jersey-2154</module>
+ <module>jersey-2160</module>
+ <module>jersey-2164</module>
+ <module>jersey-2167</module>
+ <module>jersey-2176</module>
+ <module>jersey-2184</module>
+ <module>jersey-2255</module>
+ <module>jersey-2322</module>
+ <module>jersey-2335</module>
+ <module>jersey-2421</module>
+ <module>jersey-2551</module>
+ <module>jersey-2612</module>
+ <module>jersey-2637</module>
+ <module>jersey-2654</module>
+ <module>jersey-2673</module>
+ <module>jersey-2689</module>
+ <module>jersey-2704</module>
+ <module>jersey-2776</module>
+ <module>jersey-2794</module>
+ <module>jersey-2846</module>
+ <module>jersey-2878</module>
+ <module>jersey-2892</module>
+ <module>jersey-780</module>
+ <module>portability-jersey-1</module>
+ <module>portability-jersey-2</module>
+ <module>property-check</module>
+ <module>security-digest</module>
+ <module>servlet-2.5-autodiscovery-1</module>
+ <module>servlet-2.5-autodiscovery-2</module>
+ <module>servlet-2.5-filter</module>
+ <module>servlet-2.5-inflector-1</module>
+ <module>servlet-2.5-init-1</module>
+ <module>servlet-2.5-init-2</module>
+ <module>servlet-2.5-init-3</module>
+ <module>servlet-2.5-init-4</module>
+ <module>servlet-2.5-init-5</module>
+ <module>servlet-2.5-init-6</module>
+ <module>servlet-2.5-init-7</module>
+ <module>servlet-2.5-init-8</module>
+ <module>servlet-2.5-mvc-1</module>
+ <module>servlet-2.5-mvc-2</module>
+ <module>servlet-2.5-mvc-3</module>
+ <module>servlet-2.5-reload</module>
+ <module>servlet-3-async</module>
+ <module>servlet-3-chunked-io</module>
+ <module>servlet-3-filter</module>
+ <module>servlet-3-gf-async</module>
+ <module>servlet-3-inflector-1</module>
+ <module>servlet-3-init-1</module>
+ <module>servlet-3-init-2</module>
+ <module>servlet-3-init-3</module>
+ <module>servlet-3-init-4</module>
+ <module>servlet-3-init-5</module>
+ <module>servlet-3-init-6</module>
+ <module>servlet-3-init-7</module>
+ <module>servlet-3-init-8</module>
+ <module>servlet-3-init-provider</module>
+ <module>servlet-3-params</module>
+ <module>servlet-3-sse-1</module>
+ <module>servlet-request-wrapper-binding-2</module>
+ <module>servlet-request-wrapper-binding</module>
+ <module>servlet-tests</module>
+ <module>sonar-test</module>
+ <!-- TODO: temporarily removing spring 4 integration test -->
+ <!-- TODO: conflict in ASM version (too old) of jetty plugin -->
+ <!--<module>spring4</module>-->
+ <module>tracing-support</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>default</id>
+ <properties>
+ <env>default</env>
+ <jersey.config.test.container.port>9998</jersey.config.test.container.port>
+ </properties>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <properties>
+ <env>default</env>
+ <jersey.config.test.container.port>9998</jersey.config.test.container.port>
+ <jetty.log.file>${project.build.directory}/jetty-out.log</jetty.log.file>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!-- configure Jetty to run in a separated JVM in order to get proper coverage -->
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>start-jetty-forked</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>run-forked</goal>
+ </goals>
+ <configuration>
+ <contextPath>/</contextPath>
+ <scanIntervalSeconds>0</scanIntervalSeconds>
+ <waitForChild>false</waitForChild>
+ <jvmArgs>${server.coverage.argline} -Djetty.port=${jersey.config.test.container.port}
+ -Dorg.slf4j.simpleLogger.logFile=${jetty.log.file}
+ </jvmArgs>
+ </configuration>
+ </execution>
+ <execution>
+ <id>start-jetty</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ </profiles>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <configuration>
+ <skip>${skip.tests}</skip>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ <stopPort>9999</stopPort>
+ <stopKey>STOP</stopKey>
+ <webApp>
+ <contextPath>/</contextPath>
+ <webInfIncludeJarPattern>.*/.*jersey-[^/]\.jar$</webInfIncludeJarPattern>
+ </webApp>
+ <connectors>
+ <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
+ <port>${jersey.config.test.container.port}</port>
+ <maxIdleTime>60000</maxIdleTime>
+ </connector>
+ </connectors>
+ <jvmArgs>${server.coverage.argline}</jvmArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>start-jetty</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <scanIntervalSeconds>0</scanIntervalSeconds>
+ <daemon>true</daemon>
+ </configuration>
+ </execution>
+ <execution>
+ <id>stop-jetty</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/tests/integration/portability-jersey-1/pom.xml b/tests/integration/portability-jersey-1/pom.xml
new file mode 100644
index 0000000..c8499d7
--- /dev/null
+++ b/tests/integration/portability-jersey-1/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>portability-jersey-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-portability-jersey-1</name>
+
+ <description>Servlet portability test - testing co-bundling with Jersey 1</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-servlet-portability</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.jersey-test-framework</groupId>
+ <artifactId>jersey-test-framework-external</artifactId>
+ <version>${jersey1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.jersey-test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <version>${jersey1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ <version>${jersey1.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <classpathDependencyExcludes> <!-- this is to ensure only one Jersey version is present in the classpath -->
+ <classpathDependencyExclude>org.glassfish.jersey.core:jersey-common</classpathDependencyExclude>
+ <classpathDependencyExclude>org.glassfish.jersey.core:jersey-server</classpathDependencyExclude>
+ <classpathDependencyExclude>org.glassfish.jersey.core:jersey-client</classpathDependencyExclude>
+ </classpathDependencyExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java
new file mode 100644
index 0000000..0f34d5b
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Martin Matula
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World!";
+ }
+}
diff --git a/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java
new file mode 100644
index 0000000..c56b9fa
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import com.sun.jersey.api.core.PackagesResourceConfig;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey1Application extends PackagesResourceConfig {
+ public Jersey1Application() {
+ // do the package scanning
+ super("org.glassfish.jersey.tests.integration.portability");
+
+ // explicitly add unannotated Jersey 1 specific resource
+ getExplicitRootResources().put("jersey", Jersey1Resource.class);
+ }
+}
diff --git a/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java
new file mode 100644
index 0000000..7444fcd
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey1Resource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getJersey1() {
+ return "Using Jersey 1.x";
+ }
+}
diff --git a/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java
new file mode 100644
index 0000000..91e0e1b
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey2Application extends ResourceConfig {
+
+ public Jersey2Application() {
+ // do the package scanning
+ packages("org.glassfish.jersey.tests.integration.portability");
+
+ // explicitly add unannotated Jersey 2 specific resource
+ Resource.Builder rb = Resource.builder(Jersey2Resource.class);
+ registerResources(rb.path("jersey").build());
+ }
+}
diff --git a/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java
new file mode 100644
index 0000000..f7683e3
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey2Resource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getJersey2() {
+ return "Using Jersey 2.x";
+ }
+}
diff --git a/tests/integration/portability-jersey-1/src/main/webapp/WEB-INF/web.xml b/tests/integration/portability-jersey-1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5cd3e4c
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>Jersey Web Application</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.portability.PortableServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey1#com.sun.jersey.config.property.resourceConfigClass</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.portability.Jersey1Application</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey2#javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.portability.Jersey2Application</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>Jersey Web Application</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/portability-jersey-1/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java b/tests/integration/portability-jersey-1/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java
new file mode 100644
index 0000000..8d805e8
--- /dev/null
+++ b/tests/integration/portability-jersey-1/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+import com.sun.jersey.test.framework.spi.container.TestContainerException;
+import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
+import com.sun.jersey.test.framework.spi.container.external.ExternalTestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class PortabilityITCase extends JerseyTest {
+
+ @Override
+ protected AppDescriptor configure() {
+ return new WebAppDescriptor.Builder().build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = resource().path("helloworld").get(String.class);
+ assertEquals("Hello World!", s);
+ }
+
+ @Test
+ public void testJersey() {
+ ClientResponse r = resource().path("jersey").get(ClientResponse.class);
+ assertEquals(200, r.getStatus());
+ assertEquals("Using Jersey 1.x", r.getEntity(String.class));
+ }
+
+ /**
+ * The whole project is setup for Jersey 2. Need to get the effective port number
+ * from Jersey 2 properties to make Hudson happy.
+ *
+ * @param defaultPort to use if no other configuration is available
+ * @return port number to use by the client
+ */
+ @Override
+ protected int getPort(int defaultPort) {
+
+ String port = System.getProperty("jersey.config.test.container.port");
+ if (null != port) {
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new TestContainerException("jersey.config.test.container.port with a "
+ + "value of \"" + port + "\" is not a valid integer.", e);
+ }
+ }
+
+ port = System.getProperty("JERSEY_TEST_PORT");
+ if (null != port) {
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new TestContainerException("JERSEY_TEST_PORT with a "
+ + "value of \"" + port + "\" is not a valid integer.", e);
+ }
+ }
+ return defaultPort;
+ }
+}
diff --git a/tests/integration/portability-jersey-2/pom.xml b/tests/integration/portability-jersey-2/pom.xml
new file mode 100644
index 0000000..0e63542
--- /dev/null
+++ b/tests/integration/portability-jersey-2/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>portability-jersey-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-portability-jersey-2</name>
+
+ <description>Servlet portability test - testing co-bundling with Jersey 2</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-servlet-portability</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ <version>${jersey1.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <classpathDependencyExcludes> <!-- this is to ensure only one Jersey version is present in the classpath -->
+ <classpathDependencyExclude>com.sun.jersey:jersey-core</classpathDependencyExclude>
+ <classpathDependencyExclude>com.sun.jersey:jersey-server</classpathDependencyExclude>
+ <classpathDependencyExclude>com.sun.jersey:jersey-servlet</classpathDependencyExclude>
+ </classpathDependencyExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java
new file mode 100644
index 0000000..0f34d5b
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/HelloWorldResource.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Martin Matula
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World!";
+ }
+}
diff --git a/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java
new file mode 100644
index 0000000..c56b9fa
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Application.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import com.sun.jersey.api.core.PackagesResourceConfig;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey1Application extends PackagesResourceConfig {
+ public Jersey1Application() {
+ // do the package scanning
+ super("org.glassfish.jersey.tests.integration.portability");
+
+ // explicitly add unannotated Jersey 1 specific resource
+ getExplicitRootResources().put("jersey", Jersey1Resource.class);
+ }
+}
diff --git a/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java
new file mode 100644
index 0000000..7444fcd
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey1Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey1Resource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getJersey1() {
+ return "Using Jersey 1.x";
+ }
+}
diff --git a/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java
new file mode 100644
index 0000000..91e0e1b
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Application.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey2Application extends ResourceConfig {
+
+ public Jersey2Application() {
+ // do the package scanning
+ packages("org.glassfish.jersey.tests.integration.portability");
+
+ // explicitly add unannotated Jersey 2 specific resource
+ Resource.Builder rb = Resource.builder(Jersey2Resource.class);
+ registerResources(rb.path("jersey").build());
+ }
+}
diff --git a/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java
new file mode 100644
index 0000000..f7683e3
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/java/org/glassfish/jersey/tests/integration/portability/Jersey2Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Martin Matula
+ */
+public class Jersey2Resource {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getJersey2() {
+ return "Using Jersey 2.x";
+ }
+}
diff --git a/tests/integration/portability-jersey-2/src/main/webapp/WEB-INF/web.xml b/tests/integration/portability-jersey-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5cd3e4c
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>Jersey Web Application</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.portability.PortableServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey1#com.sun.jersey.config.property.resourceConfigClass</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.portability.Jersey1Application</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey2#javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.portability.Jersey2Application</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>Jersey Web Application</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/portability-jersey-2/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java b/tests/integration/portability-jersey-2/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java
new file mode 100644
index 0000000..b158fda
--- /dev/null
+++ b/tests/integration/portability-jersey-2/src/test/java/org/glassfish/jersey/tests/integration/portability/PortabilityITCase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.portability;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class PortabilityITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target("helloworld").request().get(String.class);
+ assertEquals("Hello World!", s);
+ }
+
+ @Test
+ public void testJersey() {
+ Response r = target("jersey").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("Using Jersey 2.x", r.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/property-check/pom.xml b/tests/integration/property-check/pom.xml
new file mode 100644
index 0000000..7fd7e4b
--- /dev/null
+++ b/tests/integration/property-check/pom.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>property-check</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-integration-property-check</name>
+
+ <description>Property overlapping/duplicate check test</description>
+ <!--
+ Note that whenever new *Properties.java file is created, it has to be added in the test source file
+ in order to be checked for duplicates/overlapping.
+
+ Use find . -name "*Properties.java" in the Jersey root project folder to find files to add.
+ -->
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/property-check/src/test/java/org/glassfish/jersey/tests/integration/propertycheck/PropertyOverlappingCheckTest.java b/tests/integration/property-check/src/test/java/org/glassfish/jersey/tests/integration/propertycheck/PropertyOverlappingCheckTest.java
new file mode 100644
index 0000000..ef7072e
--- /dev/null
+++ b/tests/integration/property-check/src/test/java/org/glassfish/jersey/tests/integration/propertycheck/PropertyOverlappingCheckTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.propertycheck;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.apache.connector.ApacheClientProperties;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.internal.util.PropertiesClass;
+import org.glassfish.jersey.internal.util.Property;
+import org.glassfish.jersey.internal.util.PropertyAlias;
+import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.media.multipart.MultiPartProperties;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.message.MessageProperties;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.InternalServerProperties;
+import org.glassfish.jersey.server.oauth1.OAuth1ServerProperties;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test, that there are no properties with overlapping names in known Jersey {@code *Properties} and {@code *Feature}
+ * classes.
+ * <p>
+ * For technical reasons, we do not want the property names to <i>overlap</i>.
+ * In other words, no property should contain a <i>namespace prefix</i>, that is already used as a concrete property name,
+ * such as {@code a.b} and {@code a.b.c}.
+ * </p>
+ * <p>
+ * Additionally, the test also reports all the duplicates property names found throughout the checked files.
+ * </p>
+ * <p>
+ * Note that the list of files is hardcoded directly in this test in a static array
+ * (to avoid the necessity of writing custom class loader for this test).
+ * If a java class containing properties should by included in the check, it has to be added here.
+ * Also note that the test is relying on {@link Property}, {@link PropertiesClass} and {@link PropertyAlias} annotations
+ * to recognize individual properties.
+ * </p>
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class PropertyOverlappingCheckTest {
+
+ private static final Logger log = Logger.getLogger(PropertyOverlappingCheckTest.class.getName());
+
+ private static final Class<?>[] classes = new Class[] {
+ JettyClientProperties.class,
+ ApacheClientProperties.class,
+ OAuth1ServerProperties.class,
+ ServletProperties.class,
+ CommonProperties.class,
+ MessageProperties.class,
+ ServerProperties.class,
+ InternalServerProperties.class,
+ ClientProperties.class,
+ MultiPartProperties.class,
+ TestProperties.class,
+ SseFeature.class
+ };
+
+ private static class ProblemReport {
+
+ private final String parentProperty;
+ private final String classNameParent;
+ private final String childProperty;
+ private final String classNameChild;
+ private final boolean duplicate;
+
+ private ProblemReport(String parentProperty,
+ String classNameParent,
+ String childProperty,
+ String classNameChild,
+ boolean duplicate) {
+ this.parentProperty = parentProperty;
+ this.classNameParent = classNameParent;
+ this.childProperty = childProperty;
+ this.classNameChild = classNameChild;
+ this.duplicate = duplicate;
+ }
+
+ private ProblemReport(String parentProperty, String classNameParent, String childProperty, String classNameChild) {
+ this(parentProperty, classNameParent, childProperty, classNameChild, false);
+ }
+
+ public String getParentProperty() {
+ return parentProperty;
+ }
+
+ public String getClassNameParent() {
+ return classNameParent;
+ }
+
+ public String getChildProperty() {
+ return childProperty;
+ }
+
+ public String getClassNameChild() {
+ return classNameChild;
+ }
+
+ public boolean isDuplicate() {
+ return duplicate;
+ }
+ }
+
+ @Test
+ public void test() throws IllegalAccessException {
+ List<String> allPropertyNames = new ArrayList<>();
+ Map<String, String> propertyToClassMap = new HashMap<>();
+ List<ProblemReport> problems = new ArrayList<>();
+
+ // iterate over all the string fields of above declared classes
+ for (Class<?> clazz : classes) {
+ final boolean checkFieldPropertyAnnotation = clazz.getAnnotation(PropertiesClass.class) == null;
+ Field[] fields = clazz.getFields();
+ for (Field field : fields) {
+ if (checkFieldPropertyAnnotation && field.getAnnotation(Property.class) == null) {
+ // skip fields not annotated with @Property in classes not annotated with @PropertiesClass
+ continue;
+ }
+ if (field.getAnnotation(PropertyAlias.class) != null) {
+ // skip property aliases
+ continue;
+ }
+ if (field.getType().isAssignableFrom(String.class)) {
+ String propertyValue = (String) field.get(null);
+ allPropertyNames.add(propertyValue);
+ // check if there is already such property in the map; report a problem if true or store the
+ // property-to-class relationship into the map for later use
+ String propertyMapEntry = propertyToClassMap.get(propertyValue);
+ if (propertyToClassMap.get(propertyValue) != null) {
+ // log.info("Duplicate property found: " + propertyValue + " in " +
+ // propertyMapEntry + " and "
+ // + clazz.getName() + ". Test won't fail because of this, as the check
+ // is currently disabled.");
+ // this cannot cause the test to fail, as there are aliases in ClientProperties and ServerProperties,
+ // which are by definition equal to those defined in CommonProperties
+ problems.add(new ProblemReport(propertyValue, propertyMapEntry, propertyValue, clazz.getName(), true));
+ } else {
+ propertyToClassMap.put(propertyValue, clazz.getName());
+ }
+ }
+ }
+ }
+ // sort the properties by name (natural), so that if two properties have overlapping names,
+ // they will appear one after another
+ Collections.sort(allPropertyNames);
+
+ String previousProperty = "";
+ for (String property : allPropertyNames) {
+ // is the property overlapping with the previous one?
+ // do not consider overlapping such as foo.bar vs foo.barbar, just foo.bar vs foo.bar.bar
+ if (property.startsWith(previousProperty + ".")) {
+ problems.add(new ProblemReport(previousProperty, propertyToClassMap.get(previousProperty),
+ property, propertyToClassMap.get(property)));
+ } else {
+ // the "pointer" is moved only if there was no overlapping detected in this iteration
+ // as this would potentially hide the 2nd (or n-th) property overlapping with the same one
+ previousProperty = property;
+ }
+ }
+
+ if (!problems.isEmpty()) {
+ log.severe("Property naming problems detected: ");
+ for (ProblemReport problem : problems) {
+ if (problem.isDuplicate()) {
+ log.severe("Duplicate property name: \n property: " + problem.getParentProperty()
+ + "\n class1: " + problem.getClassNameParent()
+ + "\n class2: " + problem.getClassNameChild() + "\n");
+ } else {
+ log.severe("Overlapping property names: \n property1: "
+ + problem.getParentProperty() + "\n in: " + problem.getClassNameParent()
+ + "\n property2: "
+ + problem.getChildProperty() + "\n in " + problem.getClassNameChild() + "\n");
+ }
+ }
+ }
+ // fail if problems detected
+ assertTrue(problems.isEmpty());
+ }
+}
diff --git a/tests/integration/security-digest/pom.xml b/tests/integration/security-digest/pom.xml
new file mode 100644
index 0000000..4cffdf8
--- /dev/null
+++ b/tests/integration/security-digest/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>security-digest</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-jersey-security-digest</name>
+ <url>http://maven.apache.org</url>
+
+
+ <description>Test of DIGEST authentication</description>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+
+ <configuration>
+ <!-- define login service for jetty and the realm to be used -->
+ <loginServices>
+ <loginService implementation="org.eclipse.jetty.security.HashLoginService">
+ <name>my-realm</name>
+ <config>${basedir}/src/main/resources/jetty/realm.properties</config>
+ </loginService>
+ </loginServices>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyApplication.java b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyApplication.java
new file mode 100644
index 0000000..8c480aa
--- /dev/null
+++ b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyApplication.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.securitydigest;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ *
+ * @author Miroslav Fuksa
+ */
+@ApplicationPath("/rest/*")
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ register(MyResource.class);
+ }
+}
diff --git a/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyResource.java b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyResource.java
new file mode 100644
index 0000000..7ebff65
--- /dev/null
+++ b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/MyResource.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.securitydigest;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.SecurityContext;
+
+import javax.inject.Inject;
+
+/**
+ * This resource contains methods that are secured using web.xml declarative security. Names of methods
+ * describe which user roles have access to them.
+ *
+ * @author Miroslav Fuksa
+ */
+@Path("resource")
+public class MyResource {
+ @Inject
+ SecurityContext securityContext;
+
+ @GET
+ public String getUserAdmin() {
+ return securityContext.getUserPrincipal().getName() + getAuth();
+ }
+
+ @POST
+ public String postUserAdmin(String entity) {
+ return "post-" + entity + "-" + securityContext.getUserPrincipal().getName() + getAuth();
+ }
+
+ @GET
+ @Path("sub")
+ public String getAdmin() {
+ return "subget-" + securityContext.getUserPrincipal().getName() + getAuth();
+ }
+
+ @Path("locator")
+ public Class<SubResource> getSubResourceUserAdmin() {
+ return SubResource.class;
+ }
+
+ private String getAuth() {
+ return "/scheme:" + securityContext.getAuthenticationScheme();
+ }
+
+}
diff --git a/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/SubResource.java b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/SubResource.java
new file mode 100644
index 0000000..39c6edc
--- /dev/null
+++ b/tests/integration/security-digest/src/main/java/org/glassfish/jersey/tests/integration/securitydigest/SubResource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.securitydigest;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.SecurityContext;
+
+import javax.inject.Inject;
+
+/**
+ *
+ * @author Miroslav Fuksa
+ */
+public class SubResource {
+ @Inject
+ SecurityContext securityContext;
+
+ @GET
+ public String getUserAdmin() {
+ return "locator-" + securityContext.getUserPrincipal().getName() + getAuth();
+ }
+
+ private String getAuth() {
+ return "/scheme:" + securityContext.getAuthenticationScheme();
+ }
+}
diff --git a/tests/integration/security-digest/src/main/resources/jetty/realm.properties b/tests/integration/security-digest/src/main/resources/jetty/realm.properties
new file mode 100644
index 0000000..3530df0
--- /dev/null
+++ b/tests/integration/security-digest/src/main/resources/jetty/realm.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+homer:Homer,my-user
+marge:Marge,my-admin
+bart:Bart,my-user,my-admin
diff --git a/tests/integration/security-digest/src/main/webapp/WEB-INF/web.xml b/tests/integration/security-digest/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b704f48
--- /dev/null
+++ b/tests/integration/security-digest/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <display-name>Archetype Created Web Application</display-name>
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.securitydigest.MyApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.securitydigest.MyApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.securitydigest.MyApplication</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>rest api</web-resource-name>
+ <url-pattern>/rest/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>my-user</role-name>
+ <role-name>my-admin</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>rest api</web-resource-name>
+ <url-pattern>/rest/resource/sub</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>my-admin</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>my-user</role-name>
+ </security-role>
+ <security-role>
+ <role-name>my-admin</role-name>
+ </security-role>
+
+
+ <login-config>
+ <auth-method>DIGEST</auth-method>
+ <realm-name>my-realm</realm-name>
+ </login-config>
+
+</web-app>
diff --git a/tests/integration/security-digest/src/test/java/org/glassfish/jersey/tests/integration/securitydigest/SecurityDigestAuthenticationITCase.java b/tests/integration/security-digest/src/test/java/org/glassfish/jersey/tests/integration/securitydigest/SecurityDigestAuthenticationITCase.java
new file mode 100644
index 0000000..22b422c
--- /dev/null
+++ b/tests/integration/security-digest/src/test/java/org/glassfish/jersey/tests/integration/securitydigest/SecurityDigestAuthenticationITCase.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.securitydigest;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Miroslav Fuksa
+ */
+public class SecurityDigestAuthenticationITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(MyApplication.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(new LoggingFeature(Logger.getLogger(SecurityDigestAuthenticationITCase.class.getName()),
+ LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ @Test
+ public void testResourceGet() {
+ _testResourceGet(HttpAuthenticationFeature.digest("homer", "Homer"));
+ _testResourceGet(HttpAuthenticationFeature.universal("homer", "Homer"));
+ _testResourceGet(HttpAuthenticationFeature.universalBuilder().credentialsForDigest("homer", "Homer").build());
+ _testResourceGet(HttpAuthenticationFeature.universalBuilder().credentialsForDigest("homer", "Homer")
+ .credentialsForBasic("aaa", "bbb").build());
+ }
+
+ public void _testResourceGet(HttpAuthenticationFeature feature) {
+ final Response response = target().path("rest/resource")
+ .register(feature).request().get();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("homer/scheme:DIGEST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceGet401() {
+ _testResourceGet401(HttpAuthenticationFeature.digest("nonexisting", "foo"));
+ _testResourceGet401(HttpAuthenticationFeature.universalBuilder().credentials("nonexisting", "foo").build());
+ }
+
+ public void _testResourceGet401(HttpAuthenticationFeature feature) {
+ final Response response = target().path("rest/resource")
+ .register(feature).request().get();
+
+ Assert.assertEquals(401, response.getStatus());
+ }
+
+ @Test
+ public void testResourcePost() {
+ _testResourcePost(HttpAuthenticationFeature.digest("homer", "Homer"));
+ _testResourcePost(HttpAuthenticationFeature.universal("homer", "Homer"));
+ }
+
+ public void _testResourcePost(HttpAuthenticationFeature feature) {
+ final Response response = target().path("rest/resource")
+ .register(feature).request()
+ .post(Entity.entity("helloworld", MediaType.TEXT_PLAIN_TYPE));
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("post-helloworld-homer/scheme:DIGEST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceSubGet403() {
+ _testResourceSubGet403(HttpAuthenticationFeature.digest("homer", "Homer"));
+ _testResourceSubGet403(HttpAuthenticationFeature.universal("homer", "Homer"));
+ }
+
+ public void _testResourceSubGet403(HttpAuthenticationFeature feature) {
+ final Response response = target().path("rest/resource/sub")
+ .register(feature).request().get();
+
+ Assert.assertEquals(403, response.getStatus());
+ }
+
+ @Test
+ public void testResourceSubGet() {
+ _testResourceSubGet2(HttpAuthenticationFeature.digest("bart", "Bart"));
+ _testResourceSubGet2(HttpAuthenticationFeature.universal("bart", "Bart"));
+ }
+
+ public void _testResourceSubGet2(HttpAuthenticationFeature feature) {
+ final Response response = target().path("rest/resource/sub")
+ .register(feature).request().get();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("subget-bart/scheme:DIGEST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceLocatorGet() {
+ _testResourceLocatorGet(HttpAuthenticationFeature.digest("bart", "Bart"));
+ _testResourceLocatorGet(HttpAuthenticationFeature.universal("bart", "Bart"));
+ }
+
+ public void _testResourceLocatorGet(HttpAuthenticationFeature feature) {
+
+ final Response response = target().path("rest/resource/locator")
+ .register(feature).request().get();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("locator-bart/scheme:DIGEST", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceMultipleRequestsWithOneFilter() {
+ _testResourceMultipleRequestsWithOneFilter(HttpAuthenticationFeature.digest("homer", "Homer"));
+ _testResourceMultipleRequestsWithOneFilter(HttpAuthenticationFeature.universal("homer", "Homer"));
+ }
+
+ public void _testResourceMultipleRequestsWithOneFilter(HttpAuthenticationFeature haf) {
+ WebTarget target = target().path("rest/resource")
+ .register(haf);
+ Response response = target.request().get();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("homer/scheme:DIGEST", response.readEntity(String.class));
+
+ response = target.request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("homer/scheme:DIGEST", response.readEntity(String.class));
+
+ response = target.path("sub").request().get();
+ Assert.assertEquals(403, response.getStatus());
+
+ response = target.request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("homer/scheme:DIGEST", response.readEntity(String.class));
+
+ response = target.path("locator").request().get();
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("locator-homer/scheme:DIGEST", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/pom.xml b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
new file mode 100644
index 0000000..65d81ff
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-autodiscovery-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-autodiscovery-1</name>
+
+ <description>Servlet integration test - servlet-2.5-autodiscovery-1 - auto-discovery of UriConnegFilter</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResource.java b/tests/integration/servlet-2.5-autodiscovery-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResource.java
new file mode 100644
index 0000000..cc161c9
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_1;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
+
+/**
+ * @author Martin Matula
+ * @author Michal Gajdos
+ */
+@Path("/abc")
+public class LanguageVariantResource {
+
+ @GET
+ public Response doGet(@Context Request r) {
+ List<Variant> vs = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.valueOf("application/foo"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .mediaTypes(MediaType.valueOf("application/bar"))
+ .languages(new Locale("en")).languages(new Locale("fr")).add()
+ .build();
+
+ Variant v = r.selectVariant(vs);
+ if (v == null) {
+ return Response.notAcceptable(vs).build();
+ } else {
+ return Response.ok(v.getMediaType().toString() + ", " + v.getLanguage(), v).build();
+ }
+ }
+}
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-autodiscovery-1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d45de83
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testAutoDiscovery1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_1</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.mediaTypeMappings</param-name>
+ <param-value>foo : application/foo, bar : application/bar</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.languageMappings</param-name>
+ <param-value>english : en, french : fr</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testAutoDiscovery1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResourceITCase.java b/tests/integration/servlet-2.5-autodiscovery-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResourceITCase.java
new file mode 100644
index 0000000..af45d99
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_1/LanguageVariantResourceITCase.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_1;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class LanguageVariantResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(LanguageVariantResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testMediaTypesAndLanguages() {
+ _test("english", "foo", "en", "application/foo");
+ _test("french", "foo", "fr", "application/foo");
+
+ _test("english", "bar", "en", "application/bar");
+ _test("french", "bar", "fr", "application/bar");
+ }
+
+ private void _test(String ul, String um, String l, String m) {
+ Response r = target().path("abc." + ul + "." + um).request().get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+
+ r = target().path("abc." + um + "." + ul).request().get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+
+ r = target().path("abc").request(m).header(HttpHeaders.ACCEPT_LANGUAGE, l).get();
+ assertEquals(m + ", " + l, r.readEntity(String.class));
+ assertEquals(l, r.getLanguage().toString());
+ assertEquals(m, r.getMediaType().toString());
+ }
+}
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/pom.xml b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
new file mode 100644
index 0000000..cc220e3
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-autodiscovery-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-autodiscovery-2</name>
+
+ <description>Servlet integration test - servlet-2.5-autodiscovery-2 - auto-discovery of Bean Validation (JAX-RS bundle)</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.bundles</groupId>
+ <artifactId>jaxrs-ri</artifactId>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResource.java b/tests/integration/servlet-2.5-autodiscovery-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResource.java
new file mode 100644
index 0000000..50158e8
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResource.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_2;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+public class ValidationResource {
+
+ @POST
+ @NotNull
+ public String post(@NotNull @Size(min = 1) final String value) {
+ return value.isEmpty() || "|".equals(value) ? null : value;
+ }
+}
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-autodiscovery-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fbadfc6
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testAutoDiscovery2</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_2</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testAutoDiscovery2</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResourceITCase.java b/tests/integration/servlet-2.5-autodiscovery-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResourceITCase.java
new file mode 100644
index 0000000..646aeda
--- /dev/null
+++ b/tests/integration/servlet-2.5-autodiscovery-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_autodiscovery_2/ValidationResourceITCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_autodiscovery_2;
+
+import javax.ws.rs.client.Entity;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class ValidationResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(ValidationResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testValidationPositive() {
+ assertEquals("value", target().request().post(Entity.text("value")).readEntity(String.class));
+ }
+
+ @Test
+ public void testValidationRequestNegative() {
+ assertEquals(500, target().request().post(Entity.text("|")).getStatus());
+ }
+
+ @Test
+ public void testValidatioResponsenNegative() {
+ assertEquals(400, target().request().post(null).getStatus());
+ }
+}
diff --git a/tests/integration/servlet-2.5-filter/pom.xml b/tests/integration/servlet-2.5-filter/pom.xml
new file mode 100644
index 0000000..60416db
--- /dev/null
+++ b/tests/integration/servlet-2.5-filter/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-filter</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-filter</name>
+
+ <description>Servlet integration test - servlet-2.5-filter</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-2.5-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResource.java b/tests/integration/servlet-2.5-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResource.java
new file mode 100644
index 0000000..3f0a802
--- /dev/null
+++ b/tests/integration/servlet-2.5-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_2_5_filter;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("myresource")
+public class MyResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "OK";
+ }
+}
diff --git a/tests/integration/servlet-2.5-filter/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..4b8aefa
--- /dev/null
+++ b/tests/integration/servlet-2.5-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>Jersey Web Application</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_2_5_filter</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.filter.contextPath</param-name>
+ <param-value>/myapp/</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>Jersey Web Application</filter-name>
+ <url-pattern>/myapp/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResourceITCase.java b/tests/integration/servlet-2.5-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResourceITCase.java
new file mode 100644
index 0000000..824a01c
--- /dev/null
+++ b/tests/integration/servlet-2.5-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_2_5_filter/MyResourceITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_2_5_filter;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MyResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig rc = new ResourceConfig();
+ return rc.packages(MyResourceITCase.class.getPackage().getName());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testMyResource() throws Exception {
+ final Response response = target().path("myapp").path("myresource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testWadl() {
+ final Response response = target().path("myapp/application.wadl").request().get();
+ assertEquals(200, response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith("<?xml version=\"1.0\""));
+ }
+}
diff --git a/tests/integration/servlet-2.5-inflector-1/pom.xml b/tests/integration/servlet-2.5-inflector-1/pom.xml
new file mode 100644
index 0000000..a9f968c
--- /dev/null
+++ b/tests/integration/servlet-2.5-inflector-1/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-inflector-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-inflector-1</name>
+
+ <description>
+ Servlet integration test - servlet-2.5-inflector-1 - Check that inflectors in programmatically created resources are
+ properly injected.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyApplication.java b/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyApplication.java
new file mode 100644
index 0000000..ec9d5ec
--- /dev/null
+++ b/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_inflector_1;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ final Resource.Builder resourceBuilder = Resource.builder("resource");
+
+ resourceBuilder.addChildResource("class")
+ .addMethod("GET")
+ .handledBy(MyInflector.class);
+ resourceBuilder.addChildResource("instance")
+ .addMethod("GET")
+ .handledBy(new MyInflector());
+
+ registerResources(resourceBuilder.build());
+ }
+}
diff --git a/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyInflector.java b/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyInflector.java
new file mode 100644
index 0000000..84c9a3b
--- /dev/null
+++ b/tests/integration/servlet-2.5-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/MyInflector.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_inflector_1;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.process.Inflector;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyInflector implements Inflector<ContainerRequestContext, Response> {
+
+ @Inject
+ private Provider<HttpServletRequest> requestProvider;
+ @Inject
+ private Provider<HttpServletResponse> responseProvider;
+
+ @Override
+ public Response apply(final ContainerRequestContext requestContext) {
+ final StringBuilder stringBuilder = new StringBuilder();
+
+ // Request provider & request.
+ if (requestProvider != null) {
+ stringBuilder.append("requestProvider_");
+ stringBuilder.append(requestProvider.get() != null ? "request" : null);
+ } else {
+ stringBuilder.append("null_null");
+ }
+
+ stringBuilder.append('_');
+
+ // Response provider & response.
+ if (responseProvider != null) {
+ stringBuilder.append("responseProvider_");
+ stringBuilder.append(responseProvider.get() != null ? "response" : null);
+ } else {
+ stringBuilder.append("null_null");
+ }
+
+ return Response.ok(stringBuilder.toString()).build();
+ }
+}
diff --git a/tests/integration/servlet-2.5-inflector-1/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-inflector-1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2806fe6
--- /dev/null
+++ b/tests/integration/servlet-2.5-inflector-1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_25_inflector_1.MyApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_inflector_1.MyApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_25_inflector_1.MyApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/InflectorInjectionTestITCase.java b/tests/integration/servlet-2.5-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/InflectorInjectionTestITCase.java
new file mode 100644
index 0000000..9ccb2cb
--- /dev/null
+++ b/tests/integration/servlet-2.5-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_inflector_1/InflectorInjectionTestITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_inflector_1;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class InflectorInjectionTestITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInflectorClassInjection() throws Exception {
+ _testInflectorInjection("class");
+ }
+
+ @Test
+ public void testInflectorInstanceInjection() throws Exception {
+ _testInflectorInjection("instance");
+ }
+
+ private void _testInflectorInjection(final String path) {
+ final Response response = target("resource").path(path).request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("requestProvider_request_responseProvider_response", response.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/pom.xml b/tests/integration/servlet-2.5-init-1/pom.xml
new file mode 100644
index 0000000..71dd7e5
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-1</name>
+
+ <description>Servlet integration test - servlet-2.5-init-1 - configured via jax-rs application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/ClientUsingResource.java b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/ClientUsingResource.java
new file mode 100644
index 0000000..0728579
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/ClientUsingResource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import java.net.URI;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * A resource that instantiated & uses JAX-RS/Jersey client to access another resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("viaclient")
+public class ClientUsingResource {
+ @Path("helloworld")
+ @GET
+ public String getProxiedMessage(@Context UriInfo uriInfo) {
+ return ClientBuilder.newClient()
+ .target(uriInfo.resolve(URI.create("helloworld")))
+ .request("text/plain")
+ .get(String.class);
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/HelloWorldResource.java b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/HelloWorldResource.java
new file mode 100644
index 0000000..2ab6f5b
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/HelloWorldResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.servlet.WebConfig;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Martin Matula
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+
+ @GET
+ @Path("injection")
+ public String getInjection(@Context HttpServletRequest request, @Context HttpServletResponse response,
+ @Context WebConfig webConfig, @Context ServletConfig servletConfig,
+ @Context ServletContext servletContext) {
+ return request.getMethod() + (response != null) + webConfig.getName() + servletConfig.getServletName()
+ + servletContext.getServletContextName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/MultipleLinksResource.java b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/MultipleLinksResource.java
new file mode 100644
index 0000000..adcafea
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/MultipleLinksResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import java.net.URI;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Reproducer for JERSEY-1801. See also E2E {@code LinkTest}.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("links")
+public class MultipleLinksResource {
+
+ @GET
+ public Response get(@Context UriInfo uriInfo) throws Exception {
+ URI test1 = URI.create(uriInfo.getAbsolutePath().toString() + "test1");
+ URI test2 = URI.create(uriInfo.getAbsolutePath().toString() + "test2");
+
+ return Response.ok()
+ .link("http://oracle.com", "parent")
+ .link(new URI("http://jersey.java.net"), "framework")
+ .links(
+ Link.fromUri(uriInfo.relativize(test1)).rel("test1").build(),
+ Link.fromUri(test2).rel("test2").build(),
+ Link.fromUri(uriInfo.relativize(URI.create("links/test3"))).rel("test3").build()
+ ).build();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25init1.java b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25init1.java
new file mode 100644
index 0000000..b6aec66
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25init1.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * JAX-RS application for the Servlet 2.5 initialization test #01.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@ApplicationPath("application_path")
+public class Servlet25init1 extends Application {
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<>(
+ Arrays.asList(HelloWorldResource.class, MultipleLinksResource.class, ClientUsingResource.class));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/UnreachableResource.java b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/UnreachableResource.java
new file mode 100644
index 0000000..42e042a
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/UnreachableResource.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Martin Matula
+ */
+@Path("unreachable")
+public class UnreachableResource {
+ @GET
+ public Response get() {
+ return Response.ok().build();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-1/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d5a0798
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_1.Servlet25init1</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/servlet_path/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java b/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java
new file mode 100644
index 0000000..7ee6968
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_1;
+
+import java.net.URI;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.uri.UriTemplate;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Servlet 2.5 initialization test #01.
+ *
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Martin Matula
+ */
+public class Servlet25Init1ITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Servlet25init1();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("servlet_path/helloworld").request().get(String.class);
+ assertEquals("Hello World! " + this.getClass().getPackage().getName(), s);
+ }
+
+ @Test
+ public void testHelloWorldAtWrongPath() {
+ Response r = target().path("application_path/helloworld").request().get();
+ assertTrue(
+ "Request to application_path/helloworld should have failed, but did not. That means two applications are "
+ + "registered.",
+ r.getStatus() >= 400);
+ }
+
+ @Test
+ public void testHelloWorldViaClientInResource() throws Exception {
+ String s = target().path("servlet_path/viaclient/helloworld").request().get(String.class);
+ assertEquals("Hello World! " + this.getClass().getPackage().getName(), s);
+ }
+
+ @Test
+ public void testUnreachableResource() {
+ Response r = target().path("servlet_path/unreachable").request().get();
+ assertTrue("Managed to reach a resource that is not registered in the application.", r.getStatus() >= 400);
+ }
+
+ @Test
+ public void testUnreachableResourceAtWrongPath() {
+ Response r = target().path("application_path/unreachable").request().get();
+ assertTrue("Managed to reach a resource that is not registered in the application.", r.getStatus() >= 400);
+ }
+
+ @Test
+ public void testInjection() {
+ String s = target().path("servlet_path/helloworld/injection").request().get(String.class);
+ assertEquals("GETtruetestServlet1testServlet1/", s);
+ }
+
+ // Reproducer for JERSEY-1801
+ @Test
+ public void multipleLinksTest() {
+ final WebTarget target = target("/servlet_path/links/");
+ final Response response = target.request().get();
+ assertThat(response.getStatus(), equalTo(200));
+
+ final URI targetUri = target.getUri();
+ assertThat(response.getLink("parent").getUri(), equalTo(URI.create("http://oracle.com")));
+ assertThat(response.getLink("framework").getUri(), equalTo(URI.create("http://jersey.java.net")));
+
+ assertThat(response.getLink("test1").getUri(), equalTo(UriTemplate.resolve(targetUri, "test1")));
+ assertThat(response.getLink("test2").getUri(), equalTo(UriTemplate.resolve(targetUri, "test2")));
+ assertThat(response.getLink("test3").getUri(), equalTo(UriTemplate.resolve(targetUri, "test3")));
+ }
+
+}
diff --git a/tests/integration/servlet-2.5-init-2/pom.xml b/tests/integration/servlet-2.5-init-2/pom.xml
new file mode 100644
index 0000000..b069eff
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-2</name>
+
+ <description>Servlet integration test - servlet-2.5-init-2 - configured using package scanning</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/CustomFeature.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/CustomFeature.java
new file mode 100644
index 0000000..1f99758
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/CustomFeature.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.tests.integration.servlet_25_init_2.ext.Ext1WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_25_init_2.ext.Ext2WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_25_init_2.ext.Ext3WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_25_init_2.ext.Ext4WriterInterceptor;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class CustomFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(Ext3WriterInterceptor.class, 1000);
+ context.register(Ext2WriterInterceptor.class, 100);
+ context.register(Ext1WriterInterceptor.INSTANCE, 500);
+ context.register(Ext4WriterInterceptor.INSTANCE, 1);
+ return true;
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResource.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResource.java
new file mode 100644
index 0000000..3867cd2
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext1WriterInterceptor.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext1WriterInterceptor.java
new file mode 100644
index 0000000..1ff8e53
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext1WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext1WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext1WriterInterceptor INSTANCE = new Ext1WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext1");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext2WriterInterceptor.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext2WriterInterceptor.java
new file mode 100644
index 0000000..80eebfe
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext2WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext2WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext2");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext3WriterInterceptor.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext3WriterInterceptor.java
new file mode 100644
index 0000000..885f151
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext3WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext3WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext3");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext4WriterInterceptor.java b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext4WriterInterceptor.java
new file mode 100644
index 0000000..d90988a
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/ext/Ext4WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext4WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext4WriterInterceptor INSTANCE = new Ext4WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext4");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-2/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7066c4b
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testServlet2</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_2</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.provider.scanning.recursive</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet2</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..89071b3
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_2/HelloWorldResourceITCase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_2;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ Response r = target().path("helloworld").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("Hello World! " + this.getClass().getPackage().getName() + "-ext4-ext2-ext1-ext3",
+ r.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-3/pom.xml b/tests/integration/servlet-2.5-init-3/pom.xml
new file mode 100644
index 0000000..2271b3d
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-3/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-3</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-3</name>
+
+ <description>Servlet integration test - servlet-2.5-init-3 - configured by explicitly set resource classes</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResource.java b/tests/integration/servlet-2.5-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResource.java
new file mode 100644
index 0000000..3df9bbe
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_3;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-3/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-3/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ad4c999
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-3/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testServlet3</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_3.HelloWorldResource</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet3</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..ac2c4fe
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_3/HelloWorldResourceITCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_3;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-4/pom.xml b/tests/integration/servlet-2.5-init-4/pom.xml
new file mode 100644
index 0000000..2b119f0
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-4/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-4</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-4</name>
+
+ <description>Servlet integration test - servlet-2.5-init-4 - configured by explicitly set resource and provider class name</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResource.java b/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResource.java
new file mode 100644
index 0000000..ebf7b5b
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_4;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public Hello get() {
+ return new Hello();
+ }
+
+ public static class Hello {
+
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWriter.java b/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWriter.java
new file mode 100644
index 0000000..54113d1
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWriter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_4;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Provider
+public class HelloWriter implements MessageBodyWriter<HelloWorldResource.Hello> {
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(HelloWorldResource.Hello.class);
+ }
+
+ @Override
+ public long getSize(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ entityStream.write(("Hello World! " + this.getClass().getPackage().getName())
+ .getBytes(MessageUtils.getCharset(mediaType)));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-4/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-4/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b3b168e
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-4/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>testServlet4</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_4.HelloWorldResource;org.glassfish.jersey.tests.integration.servlet_25_init_4.HelloWriter</param-value>
+ </init-param>
+
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet4</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..c16b5ff
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_4/HelloWorldResourceITCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_4;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-5/pom.xml b/tests/integration/servlet-2.5-init-5/pom.xml
new file mode 100644
index 0000000..bce35f3
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-5</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-5</name>
+
+ <description>Servlet integration test - servlet-2.5-init-5 - filter with specified jax rs application class</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResource.java b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResource.java
new file mode 100644
index 0000000..16003d3
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_5;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("filter_path/helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/Servlet25init5.java b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/Servlet25init5.java
new file mode 100644
index 0000000..272e070
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/Servlet25init5.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_5;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@ApplicationPath("application_path")
+public class Servlet25init5 extends Application{
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.singleton(HelloWorldResource.class);
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/UnreachableResource.java b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/UnreachableResource.java
new file mode 100644
index 0000000..24eee33
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/UnreachableResource.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_5;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Martin Matula
+ */
+@Path("filter_path/unreachable")
+public class UnreachableResource {
+ @GET
+ public Response get() {
+ return Response.ok().build();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-5/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-5/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..271170f
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>testServlet5</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_5.Servlet25init5</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testServlet5</filter-name>
+ <url-pattern>/filter_path/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..561412a
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_5/HelloWorldResourceITCase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_5;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("filter_path/helloworld").request().get(String.class);
+ assertEquals("Hello World! " + this.getClass().getPackage().getName(), s);
+ }
+
+ @Test
+ public void testHelloWorldAtWrongPath() {
+ Response r = target().path("application_path/filter_path/helloworld").request().get();
+ assertTrue(
+ "Request to application_path/helloworld should have failed, but did not. That means two applications are "
+ + "registered.",
+ r.getStatus() >= 400);
+ }
+
+ @Test
+ @Ignore
+ public void testUnreachableResource() {
+ Response r = target().path("filter_path/unreachable").request().get();
+ assertTrue("Managed to reach a resource that is not registered in the application.", r.getStatus() >= 400);
+ }
+
+ @Test
+ public void testUnreachableResourceAtWrongPath() {
+ Response r = target().path("application_path/filter_path/unreachable").request().get();
+ assertTrue("Managed to reach a resource that is not registered in the application.", r.getStatus() >= 400);
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-6/pom.xml b/tests/integration/servlet-2.5-init-6/pom.xml
new file mode 100644
index 0000000..aa89759
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-6/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-6</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-6</name>
+
+ <description>Servlet integration test - servlet-2.5-init-6 - filter - configured using package scanning</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResource.java b/tests/integration/servlet-2.5-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResource.java
new file mode 100644
index 0000000..0d5c6e3
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_6;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-6/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-6/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..df4e84f
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-6/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>testServlet6</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_6</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testServlet6</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..e10063f
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_6/HelloWorldResourceITCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_6;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-7/pom.xml b/tests/integration/servlet-2.5-init-7/pom.xml
new file mode 100644
index 0000000..231efe9
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-7/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-7</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-7</name>
+
+ <description>Servlet integration test - servlet-2.5-init-7 - filter - configured by explicitly set resource classes</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResource.java b/tests/integration/servlet-2.5-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResource.java
new file mode 100644
index 0000000..3b924d4
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_7;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-7/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-7/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..859d505
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-7/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>testServlet7</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_7.HelloWorldResource</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testServlet7</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..b1edf72
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_7/HelloWorldResourceITCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_7;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-8/pom.xml b/tests/integration/servlet-2.5-init-8/pom.xml
new file mode 100644
index 0000000..bb916ce
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-8/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-init-8</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-init-8</name>
+
+ <description>Servlet integration test - servlet-2.5-init-8 - filter - configured by explicitly set resource and provider class name</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResource.java b/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResource.java
new file mode 100644
index 0000000..ab3917d
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public Hello get() {
+ return new Hello();
+ }
+
+ public static class Hello {
+
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWriter.java b/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWriter.java
new file mode 100644
index 0000000..62dcb6f
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWriter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_8;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Provider
+public class HelloWriter implements MessageBodyWriter<HelloWorldResource.Hello> {
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(HelloWorldResource.Hello.class);
+ }
+
+ @Override
+ public long getSize(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ entityStream.write(("Hello World! " + this.getClass().getPackage().getName())
+ .getBytes(MessageUtils.getCharset(mediaType)));
+ }
+}
diff --git a/tests/integration/servlet-2.5-init-8/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-init-8/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1aaa6d3
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-8/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>testServlet8</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_init_8.HelloWorldResource;org.glassfish.jersey.tests.integration.servlet_25_init_8.HelloWriter</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testServlet8</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResourceITCase.java b/tests/integration/servlet-2.5-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..ba304ba
--- /dev/null
+++ b/tests/integration/servlet-2.5-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_8/HelloWorldResourceITCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_init_8;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/pom.xml b/tests/integration/servlet-2.5-mvc-1/pom.xml
new file mode 100644
index 0000000..4423806
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-mvc-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-mvc-1</name>
+
+ <description>Servlet integration test - servlet-2.5-mvc-1 - filter - MVC</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-jsp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/MyApplication.java b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/MyApplication.java
new file mode 100644
index 0000000..973f3ce
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/MyApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource.Bookstore;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ // Resources.
+ packages(Bookstore.class.getPackage().getName());
+
+ // MVC.
+ register(JspMvcFeature.class);
+
+ // Logging.
+ register(LoggingFeature.class);
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book.java b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book.java
new file mode 100644
index 0000000..8401757
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Book extends Item {
+
+ public Book() {
+ }
+
+ public Book(final String title, final String author) {
+ super(title, author);
+ }
+
+
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore.java b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore.java
new file mode 100644
index 0000000..f66b7b3
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+
+@Path("/")
+@Singleton
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Bookstore {
+
+ private final Map<String, Item> items = new TreeMap<String, Item>();
+ private String name;
+
+ public Bookstore() {
+ setName("Czech Bookstore");
+ getItems().put("1", new Book("Svejk", "Jaroslav Hasek"));
+ getItems().put("2", new Book("Krakatit", "Karel Capek"));
+ }
+
+ @Path("items/{itemid}/")
+ public Item getItem(@PathParam("itemid") String itemid) {
+ Item i = getItems().get(itemid);
+ if (i == null) {
+ throw new NotFoundException(Response
+ .status(Response.Status.NOT_FOUND)
+ .entity("Item, " + itemid + ", is not found")
+ .build());
+ }
+
+ return i;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Bookstore getXml() {
+ return this;
+ }
+
+ public Map<String, Item> getItems() {
+ return items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item.java b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item.java
new file mode 100644
index 0000000..9a01b41
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Item {
+
+ private String title;
+ private String author;
+
+ public Item() {
+ }
+
+ public Item(final String title, final String author) {
+ this.title = title;
+ this.author = author;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Item getXml() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "Item{"
+ + "title='" + title + '\''
+ + ", author='" + author + '\''
+ + '}';
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7692801
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_1.MyApplication</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_mvc_1.MyApplication</param-value>
+ </init-param>
+ <!-- pass to next filter if Jersey/App returns 404 -->
+ <init-param>
+ <param-name>jersey.config.servlet.filter.forwardOn404</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_1.MyApplication</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book/index.jsp b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book/index.jsp
new file mode 100644
index 0000000..bff6020
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Book/index.jsp
@@ -0,0 +1,46 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+<%--
+The taglib directive below imports the JSTL library. If you uncomment it,
+you must also add the JSTL library to the project. The Add Library... action
+on Libraries node in Projects view can be used to add the JSTL 1.1 library.
+--%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Book</title>
+ </head>
+ <body>
+
+ <h1>${it.title}</h1>
+
+ Book from ${it.author}
+
+ <rbt:include page="footer.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/count.jsp b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/count.jsp
new file mode 100644
index 0000000..2fe7542
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/count.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%--
+ An example of another side JSP.
+--%>
+<html>
+ <body>
+ # of items: ${fn:length(it.items)}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/index.jsp b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/index.jsp
new file mode 100644
index 0000000..2ddb202
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/index.jsp
@@ -0,0 +1,56 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css" media="screen">
+ @import url( <c:url value="/css/style.css"/> );
+ </style>
+ <title>REST Bookstore Sample</title>
+ </head>
+ <body>
+
+ <h1>${it.name}</h1>
+
+ <h2>Item List</h2>
+
+ <ul>
+ <c:forEach var="i" items="${it.items}">
+ <li><a href="items/${i.key}/">${i.value.title}</a>
+ </c:forEach>
+ </ul>
+
+ <h2>Others</h2>
+ <p>
+ <a href="count">count inventory</a>
+ <p>
+ <a href="time">get the system time</a>
+ <p>
+ <a href="jsp/help.jsp">regular resources</a>
+ </p>
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/time.jsp b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/time.jsp
new file mode 100644
index 0000000..527e22f
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Bookstore/time.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+ <body>
+ Current system time is ${it.systemTime}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item/footer.jsp b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item/footer.jsp
new file mode 100644
index 0000000..fdff710
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/resource/Item/footer.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<p>
+<a href="../../">Back</a>
+<hr>
+<div align="right">
+ Common footer (title ${it.title})
+</div>
diff --git a/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/BookstoreITCase.java b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/BookstoreITCase.java
new file mode 100644
index 0000000..a751b9c
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/BookstoreITCase.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource.Bookstore;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class BookstoreITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsHtml() throws Exception {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ assertBookstoreHtmlResponse(target().request(MediaType.TEXT_HTML_TYPE).get(String.class));
+ }
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final Bookstore response = target().request("application/xml").get(Bookstore.class);
+
+ assertNotNull("Should have returned a bookstore!", response);
+ assertEquals("bookstore name", "Czech Bookstore", response.getName());
+ }
+
+ @Test
+ public void testSingleContentTypeAndContentLengthValueInXmlResponse() throws Exception {
+ assertStatusContentTypeAndLength(target().request("application/xml").get());
+ assertStatusContentTypeAndLength(target()
+ .request("text/html", "application/xhtml+xml", "application/xml;q=0.9", "*/*;q=0.8").get());
+ }
+
+ private void assertStatusContentTypeAndLength(Response response) {
+ assertEquals("Should have returned a 200 response!", 200, response.getStatus());
+ assertTrue("Should contain a Content-Type header!", response.getHeaders().containsKey(HttpHeaders.CONTENT_TYPE));
+ assertEquals("Should have a single Content-Type header!", 1, response.getHeaders().get(HttpHeaders.CONTENT_TYPE).size());
+ assertTrue("Should contain a Content-Length header!", response.getHeaders().containsKey(HttpHeaders.CONTENT_LENGTH));
+ assertEquals("Should have a single Content-Length header!",
+ 1, response.getHeaders().get(HttpHeaders.CONTENT_LENGTH).size());
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final String response = target().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(String.class);
+
+ assertBookstoreHtmlResponse(response);
+ }
+
+ protected void assertBookstoreHtmlResponse(String response) {
+ assertHtmlResponse(response);
+ assertResponseContains(response, "Bookstore");
+ assertResponseContains(response, "Item List");
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/ItemITCase.java b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/ItemITCase.java
new file mode 100644
index 0000000..90d9118
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/ItemITCase.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_1.resource.Book;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ItemITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsHtml() throws Exception {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ final String response = item1resource().request(MediaType.TEXT_HTML).get(String.class);
+ assertItemHtmlResponse(response);
+ }
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final String text = item1resource().request("application/xml").get(String.class);
+ System.out.println("Item XML is: " + text);
+
+ final Book response = item1resource().request("application/xml").get(Book.class);
+ assertNotNull("Should have returned an item!", response);
+ assertEquals("item title", "Svejk", response.getTitle());
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final String response = item1resource().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(String.class);
+
+ assertItemHtmlResponse(response);
+ }
+
+ protected void assertItemHtmlResponse(String response) {
+ assertHtmlResponse(response);
+ assertResponseContains(response, "<title>Book</title>");
+ assertResponseContains(response, "<h1>Svejk</h1>");
+ }
+
+ protected WebTarget item1resource() {
+ return target().path("/items/1");
+ }
+
+}
diff --git a/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/TestSupport.java b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/TestSupport.java
new file mode 100644
index 0000000..0ae958f
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_1/TestSupport.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_1;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A base class for test cases which boots up a GlassFish server for in container testing of RESTful resources.
+ *
+ * @author James Strachan
+ * @author Naresh
+ */
+public abstract class TestSupport extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ protected void assertHtmlResponse(String response) {
+ assertNotNull("No text returned!", response);
+
+ assertResponseContains(response, "<html>");
+ assertResponseContains(response, "</html>");
+ }
+
+ protected void assertResponseContains(String response, String text) {
+ assertTrue("Response should contain " + text + " but was: " + response, response.contains(text));
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/pom.xml b/tests/integration/servlet-2.5-mvc-2/pom.xml
new file mode 100644
index 0000000..a34c50d
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-mvc-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-mvc-2</name>
+
+ <description>Servlet integration test - servlet-2.5-mvc-2 - filter - MVC - jersey.config.servlet.jsp.disableJspTemplateProcessor</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-jsp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/MyApplication.java b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/MyApplication.java
new file mode 100644
index 0000000..b3f7066
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/MyApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource.Bookstore;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ // Resources.
+ packages(Bookstore.class.getPackage().getName());
+
+ // MVC.
+ register(JspMvcFeature.class);
+
+ // Logging.
+ register(LoggingFeature.class);
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book.java b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book.java
new file mode 100644
index 0000000..5b64e83
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Book extends Item {
+
+ public Book() {
+ }
+
+ public Book(final String title, final String author) {
+ super(title, author);
+ }
+
+
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore.java b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore.java
new file mode 100644
index 0000000..aeb0812
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+
+@Path("/")
+@Singleton
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Bookstore {
+
+ private final Map<String, Item> items = new TreeMap<String, Item>();
+ private String name;
+
+ public Bookstore() {
+ setName("Czech Bookstore");
+ getItems().put("1", new Book("Svejk", "Jaroslav Hasek"));
+ getItems().put("2", new Book("Krakatit", "Karel Capek"));
+ }
+
+ @Path("items/{itemid}/")
+ public Item getItem(@PathParam("itemid") String itemid) {
+ Item i = getItems().get(itemid);
+ if (i == null) {
+ throw new NotFoundException(Response
+ .status(Response.Status.NOT_FOUND)
+ .entity("Item, " + itemid + ", is not found")
+ .build());
+ }
+
+ return i;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Bookstore getXml() {
+ return this;
+ }
+
+ public Map<String, Item> getItems() {
+ return items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item.java b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item.java
new file mode 100644
index 0000000..42ef066
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Item {
+
+ private String title;
+ private String author;
+
+ public Item() {
+ }
+
+ public Item(final String title, final String author) {
+ this.title = title;
+ this.author = author;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Item getXml() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "Item{"
+ + "title='" + title + '\''
+ + ", author='" + author + '\''
+ + '}';
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..4fa05ba
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_2.MyApplication</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_mvc_2.MyApplication</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <!-- pass to next filter if Jersey/App returns 404 -->
+ <init-param>
+ <param-name>jersey.config.servlet.filter.forwardOn404</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_2.MyApplication</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book/index.jsp b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book/index.jsp
new file mode 100644
index 0000000..bff6020
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Book/index.jsp
@@ -0,0 +1,46 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+<%--
+The taglib directive below imports the JSTL library. If you uncomment it,
+you must also add the JSTL library to the project. The Add Library... action
+on Libraries node in Projects view can be used to add the JSTL 1.1 library.
+--%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Book</title>
+ </head>
+ <body>
+
+ <h1>${it.title}</h1>
+
+ Book from ${it.author}
+
+ <rbt:include page="footer.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/count.jsp b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/count.jsp
new file mode 100644
index 0000000..2fe7542
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/count.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%--
+ An example of another side JSP.
+--%>
+<html>
+ <body>
+ # of items: ${fn:length(it.items)}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/index.jsp b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/index.jsp
new file mode 100644
index 0000000..2ddb202
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/index.jsp
@@ -0,0 +1,56 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css" media="screen">
+ @import url( <c:url value="/css/style.css"/> );
+ </style>
+ <title>REST Bookstore Sample</title>
+ </head>
+ <body>
+
+ <h1>${it.name}</h1>
+
+ <h2>Item List</h2>
+
+ <ul>
+ <c:forEach var="i" items="${it.items}">
+ <li><a href="items/${i.key}/">${i.value.title}</a>
+ </c:forEach>
+ </ul>
+
+ <h2>Others</h2>
+ <p>
+ <a href="count">count inventory</a>
+ <p>
+ <a href="time">get the system time</a>
+ <p>
+ <a href="jsp/help.jsp">regular resources</a>
+ </p>
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/time.jsp b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/time.jsp
new file mode 100644
index 0000000..527e22f
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Bookstore/time.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+ <body>
+ Current system time is ${it.systemTime}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item/footer.jsp b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item/footer.jsp
new file mode 100644
index 0000000..fdff710
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/main/webapp/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/resource/Item/footer.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<p>
+<a href="../../">Back</a>
+<hr>
+<div align="right">
+ Common footer (title ${it.title})
+</div>
diff --git a/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/BookstoreITCase.java b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/BookstoreITCase.java
new file mode 100644
index 0000000..0d20972
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/BookstoreITCase.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource.Bookstore;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class BookstoreITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final Bookstore response = target().request("application/xml").get(Bookstore.class);
+
+ assertBookstoreXmlResponse(response);
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final Response response = target().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(Response.class);
+
+ assertEquals(404, response.getStatus());
+ }
+
+ protected void assertBookstoreXmlResponse(final Bookstore response) {
+ assertNotNull("Should have returned a bookstore!", response);
+ assertEquals("bookstore name", "Czech Bookstore", response.getName());
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/ItemITCase.java b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/ItemITCase.java
new file mode 100644
index 0000000..e4a793b
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/ItemITCase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_2.resource.Book;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ItemITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final String text = item1resource().request("application/xml").get(String.class);
+ System.out.println("Item XML is: " + text);
+
+ final Book response = item1resource().request("application/xml").get(Book.class);
+ assertItemXmlResponse(response);
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final Response response = item1resource().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(Response.class);
+
+ assertEquals(404, response.getStatus());
+ }
+
+ private void assertItemXmlResponse(final Book response) {
+ assertNotNull("Should have returned an item!", response);
+ assertEquals("item title", "Svejk", response.getTitle());
+ }
+
+ protected WebTarget item1resource() {
+ return target().path("/items/1");
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/TestSupport.java b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/TestSupport.java
new file mode 100644
index 0000000..d9d2099
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_2/TestSupport.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_2;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+/**
+ * A base class for test cases which boots up a GlassFish server for in container testing of RESTful resources.
+ *
+ * @author James Strachan
+ * @author Naresh
+ */
+public abstract class TestSupport extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/pom.xml b/tests/integration/servlet-2.5-mvc-3/pom.xml
new file mode 100644
index 0000000..962b2ba
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-mvc-3</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-mvc-3</name>
+
+ <description>Servlet integration test - servlet-2.5-mvc-3 - filter - MVC - jersey.config.servlet.JspTemplatesBasePath</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-mvc-jsp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/MyApplication.java b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/MyApplication.java
new file mode 100644
index 0000000..998b5d4
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/MyApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource.Bookstore;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ // Resources.
+ packages(Bookstore.class.getPackage().getName());
+
+ // MVC.
+ register(JspMvcFeature.class);
+
+ // Logging.
+ register(LoggingFeature.class);
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book.java b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book.java
new file mode 100644
index 0000000..049a8f2
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Book extends Item {
+
+ public Book() {
+ }
+
+ public Book(final String title, final String author) {
+ super(title, author);
+ }
+
+
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore.java b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore.java
new file mode 100644
index 0000000..d52888b
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Singleton;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+
+@Path("/")
+@Singleton
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Bookstore {
+
+ private final Map<String, Item> items = new TreeMap<String, Item>();
+ private String name;
+
+ public Bookstore() {
+ setName("Czech Bookstore");
+ getItems().put("1", new Book("Svejk", "Jaroslav Ha\u0161ek"));
+ getItems().put("2", new Book("Krakatit", "Karel Capek"));
+ }
+
+ @Path("items/{itemid}/")
+ public Item getItem(@PathParam("itemid") String itemid) {
+ Item i = getItems().get(itemid);
+ if (i == null) {
+ throw new NotFoundException(Response
+ .status(Response.Status.NOT_FOUND)
+ .entity("Item, " + itemid + ", is not found")
+ .build());
+ }
+
+ return i;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Bookstore getXml() {
+ return this;
+ }
+
+ public Map<String, Item> getItems() {
+ return items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item.java b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item.java
new file mode 100644
index 0000000..85eb6cb
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.server.mvc.Template;
+import org.glassfish.jersey.server.mvc.Viewable;
+
+@Template
+@Produces("text/html")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Item {
+
+ private String title;
+ private String author;
+
+ public Item() {
+ }
+
+ public Item(final String title, final String author) {
+ this.title = title;
+ this.author = author;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Item getXml() {
+ return this;
+ }
+
+ @GET
+ @Path("utf")
+ public Viewable getItemUtf8() {
+ return new Viewable("index.utf8.jsp", this);
+ }
+
+ @GET
+ @Path("iso")
+ public Viewable getItemIso88592() {
+ return new Viewable("index.iso88592.jsp", this);
+ }
+
+ @Override
+ public String toString() {
+ return "Item{"
+ + "title='" + title + '\''
+ + ", author='" + author + '\''
+ + '}';
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..bcc550e
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_3.MyApplication</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_mvc_3.MyApplication</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
+ <param-value>/jsp/</param-value>
+ </init-param>
+ <!-- pass to next filter if Jersey/App returns 404 -->
+ <init-param>
+ <param-name>jersey.config.servlet.filter.forwardOn404</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>org.glassfish.jersey.tests.integration.servlet_25_mvc_3.MyApplication</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.iso88592.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.iso88592.jsp
new file mode 100644
index 0000000..57643b6
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.iso88592.jsp
@@ -0,0 +1,45 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="ISO-8859-2"%>
+<%--
+The taglib directive below imports the JSTL library. If you uncomment it,
+you must also add the JSTL library to the project. The Add Library... action
+on Libraries node in Projects view can be used to add the JSTL 1.1 library.
+--%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <title>Book</title>
+ </head>
+ <body>
+
+ <h1>${it.title}</h1>
+
+ Book from ${it.author}
+
+ <rbt:include page="footer.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.jsp
new file mode 100644
index 0000000..bff6020
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.jsp
@@ -0,0 +1,46 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+<%--
+The taglib directive below imports the JSTL library. If you uncomment it,
+you must also add the JSTL library to the project. The Add Library... action
+on Libraries node in Projects view can be used to add the JSTL 1.1 library.
+--%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Book</title>
+ </head>
+ <body>
+
+ <h1>${it.title}</h1>
+
+ Book from ${it.author}
+
+ <rbt:include page="footer.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.utf8.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.utf8.jsp
new file mode 100644
index 0000000..3410c60
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Book/index.utf8.jsp
@@ -0,0 +1,45 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+<%--
+The taglib directive below imports the JSTL library. If you uncomment it,
+you must also add the JSTL library to the project. The Add Library... action
+on Libraries node in Projects view can be used to add the JSTL 1.1 library.
+--%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <title>Book</title>
+ </head>
+ <body>
+
+ <h1>${it.title}</h1>
+
+ Book from ${it.author}
+
+ <rbt:include page="footer.jsp"/>
+
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/count.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/count.jsp
new file mode 100644
index 0000000..2fe7542
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/count.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%--
+ An example of another side JSP.
+--%>
+<html>
+ <body>
+ # of items: ${fn:length(it.items)}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/index.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/index.jsp
new file mode 100644
index 0000000..91796e2
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/index.jsp
@@ -0,0 +1,56 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@page contentType="text/html"%>
+<%@page pageEncoding="UTF-8"%>
+
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css" media="screen">
+ @import url( <c:url value="/css/style.css"/> );
+ </style>
+ <title>REST Bookstore Sample</title>
+ </head>
+ <body>
+
+ <h1>${it.name}</h1>
+
+ <h2>Item List</h2>
+
+ <ul>
+ <c:forEach var="i" items="${it.items}">
+ <li><a href="items/${i.key}/">${i.value.title}</a>
+ </c:forEach>
+ </ul>
+
+ <h2>Others</h2>
+ <p>
+ <a href="count">count inventory</a>
+ <p>
+ <a href="time">get the system time</a>
+ <p>
+ <a href="jsp/help.jsp">regular resources</a>
+ </p>
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/time.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/time.jsp
new file mode 100644
index 0000000..527e22f
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Bookstore/time.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+ <body>
+ Current system time is ${it.systemTime}
+ </body>
+</html>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item/footer.jsp b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item/footer.jsp
new file mode 100644
index 0000000..fdff710
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/main/webapp/jsp/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/resource/Item/footer.jsp
@@ -0,0 +1,24 @@
+<%--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<p>
+<a href="../../">Back</a>
+<hr>
+<div align="right">
+ Common footer (title ${it.title})
+</div>
diff --git a/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/BookstoreITCase.java b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/BookstoreITCase.java
new file mode 100644
index 0000000..11f57e4
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/BookstoreITCase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3;
+
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource.Bookstore;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class BookstoreITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsHtml() throws Exception {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ assertBookstoreHtmlResponse(target().request(MediaType.TEXT_HTML).get(String.class));
+ }
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final Bookstore response = target().request("application/xml").get(Bookstore.class);
+
+ assertNotNull("Should have returned a bookstore!", response);
+ assertEquals("bookstore name", "Czech Bookstore", response.getName());
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final String response = target().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(String.class);
+
+ assertBookstoreHtmlResponse(response);
+ }
+
+ protected void assertBookstoreHtmlResponse(String response) {
+ assertHtmlResponse(response);
+ assertResponseContains(response, "Bookstore");
+ assertResponseContains(response, "Item List");
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/ItemITCase.java b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/ItemITCase.java
new file mode 100644
index 0000000..b3c3e39
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/ItemITCase.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.tests.integration.servlet_25_mvc_3.resource.Book;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+public class ItemITCase extends TestSupport {
+
+ @Test
+ public void testResourceAsHtml() throws Exception {
+ // NOTE: HttpUrlConnector sends several accepted types by default when not explicitly set by the caller.
+ // In such case, the .accept("text/html") call is not necessary. However, other connectors act in a different way and
+ // this leads in different behaviour when selecting the MessageBodyWriter. Leaving the definition explicit for broader
+ // compatibility.
+ final String response = item1resource().request(MediaType.TEXT_HTML).get(String.class);
+ assertItemHtmlResponse(response);
+ }
+
+ @Test
+ public void testResourceAsHtmlUtf8() throws Exception {
+ final Response response = item1resource().path("utf").request().get();
+ final String html = response.readEntity(String.class);
+
+ assertItemHtmlResponse(html);
+ assertResponseContains(html, "Ha\u0161ek");
+ }
+
+ @Test
+ public void testResourceAsHtmlIso88592() throws Exception {
+ final Response response = item1resource().path("iso").request().get();
+ response.bufferEntity();
+
+ final String htmlUtf8 = response.readEntity(String.class);
+
+ assertItemHtmlResponse(htmlUtf8);
+ assertFalse("Response shouldn't contain Ha\u0161ek but was: " + htmlUtf8, htmlUtf8.contains("Ha\u0161ek"));
+
+ final byte[] bytes = response.readEntity(byte[].class);
+ final String htmlIso = new String(bytes, "ISO-8859-2");
+
+ assertItemHtmlResponse(htmlIso);
+ assertFalse("Response shouldn't contain Ha\u0161ek but was: " + htmlIso, htmlIso.contains("Ha\u0161ek"));
+ assertResponseContains(htmlIso, new String("Ha\u0161ek".getBytes(), "ISO-8859-2"));
+ }
+
+ @Test
+ public void testResourceAsXml() throws Exception {
+ final String text = item1resource().request("application/xml").get(String.class);
+ System.out.println("Item XML is: " + text);
+
+ final Book response = item1resource().request("application/xml").get(Book.class);
+ assertNotNull("Should have returned an item!", response);
+ assertEquals("item title", "Svejk", response.getTitle());
+ }
+
+ @Test
+ public void testResourceAsHtmlUsingWebKitAcceptHeaders() throws Exception {
+ final String response = item1resource().request(
+ "text/html",
+ "application/xhtml+xml",
+ "application/xml;q=0.9",
+ "*/*;q=0.8").get(String.class);
+
+ assertItemHtmlResponse(response);
+ }
+
+ protected void assertItemHtmlResponse(final String response) {
+ assertHtmlResponse(response);
+ assertResponseContains(response, "<title>Book</title>");
+ assertResponseContains(response, "<h1>Svejk</h1>");
+ }
+
+ protected WebTarget item1resource() {
+ return target().path("/items/1");
+ }
+}
diff --git a/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/TestSupport.java b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/TestSupport.java
new file mode 100644
index 0000000..69121ee
--- /dev/null
+++ b/tests/integration/servlet-2.5-mvc-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_mvc_3/TestSupport.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_mvc_3;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A base class for test cases which boots up a GlassFish server for in container testing of RESTful resources.
+ *
+ * @author James Strachan
+ * @author Naresh
+ */
+public abstract class TestSupport extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+ return new MyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ protected void assertHtmlResponse(final String response) {
+ assertNotNull("No text returned!", response);
+
+ assertResponseContains(response, "<html>");
+ assertResponseContains(response, "</html>");
+ }
+
+ protected void assertResponseContains(final String response, final String text) {
+ assertTrue("Response should contain " + text + " but was: " + response, response.contains(text));
+ }
+}
diff --git a/tests/integration/servlet-2.5-reload/pom.xml b/tests/integration/servlet-2.5-reload/pom.xml
new file mode 100644
index 0000000..29de897
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-2.5-reload</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-2.5-reload</name>
+
+ <description>Servlet integration test - servlet-2.5-reload - reload resource triggers application reload</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/AnotherResource.java b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/AnotherResource.java
new file mode 100644
index 0000000..49e28ec
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/AnotherResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_config_reload;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("another")
+public class AnotherResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Another resource";
+ }
+}
diff --git a/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/HelloWorldResource.java b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/HelloWorldResource.java
new file mode 100644
index 0000000..2fdcb63
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_config_reload;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World! " + this.getClass().getPackage().getName();
+ }
+}
diff --git a/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadContainerLifecycleListener.java b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadContainerLifecycleListener.java
new file mode 100644
index 0000000..ceee204
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadContainerLifecycleListener.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_config_reload;
+
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+
+/**
+ * @author Miroslav Fuksa
+ */
+@Provider
+public class ReloadContainerLifecycleListener extends AbstractContainerLifecycleListener {
+
+ private static Container container;
+
+ @Override
+ public void onStartup(final Container container) {
+ ReloadContainerLifecycleListener.setContainer(container);
+ }
+
+ public static Container getContainer() {
+ return container;
+ }
+
+ public static void setContainer(final Container container) {
+ ReloadContainerLifecycleListener.container = container;
+ }
+
+}
diff --git a/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadResource.java b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadResource.java
new file mode 100644
index 0000000..e2c1c46
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/main/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_config_reload;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("reload")
+public class ReloadResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ try {
+ ReloadContainerLifecycleListener.getContainer().reload(
+ new ResourceConfig(HelloWorldResource.class,
+ ReloadResource.class,
+ AnotherResource.class,
+ ReloadContainerLifecycleListener.class)
+ );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ return "Reload resource";
+ }
+}
diff --git a/tests/integration/servlet-2.5-reload/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-2.5-reload/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..14a0f9c
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>JerseyReloadServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_25_config_reload.ReloadResource org.glassfish.jersey.tests.integration.servlet_25_config_reload.HelloWorldResource
+ org.glassfish.jersey.tests.integration.servlet_25_config_reload.ReloadResource org.glassfish.jersey.tests.integration.servlet_25_config_reload.ReloadContainerLifecycleListener</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JerseyReloadServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-2.5-reload/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadTestIT.java b/tests/integration/servlet-2.5-reload/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadTestIT.java
new file mode 100644
index 0000000..af22617
--- /dev/null
+++ b/tests/integration/servlet-2.5-reload/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_config_reload/ReloadTestIT.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_25_config_reload;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class ReloadTestIT extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testReload() throws Exception {
+ Response response = target().path("helloworld").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("Hello World! " + this.getClass().getPackage().getName(), response.readEntity(String.class));
+
+ response = target().path("another").request().get();
+ assertEquals(404, response.getStatus());
+
+ response = target().path("reload").request().get();
+ assertEquals(200, response.getStatus());
+
+ response = target().path("another").request().get();
+ assertEquals(200, response.getStatus());
+ }
+}
diff --git a/tests/integration/servlet-3-async/pom.xml b/tests/integration/servlet-3-async/pom.xml
new file mode 100644
index 0000000..a959490
--- /dev/null
+++ b/tests/integration/servlet-3-async/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-async</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-async</name>
+
+ <description>Servlet integration test - servlet-3-async - configured via jax-rs application annotated with @javax.ws.rs.ApplicationPath</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java
new file mode 100644
index 0000000..2f96055
--- /dev/null
+++ b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+/**
+ * Asynchronous servlet-deployed resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("async")
+public class AsyncServletResource {
+ /**
+ * Hello world message.
+ */
+ public static final String HELLO_ASYNC_WORLD = "Hello Async World!";
+ public static final String CANCELED = "Canceled";
+
+ private static BlockingQueue<CanceledRequest> cancelingQueue = new ArrayBlockingQueue<CanceledRequest>(5);
+
+ private static class CanceledRequest {
+ private final String id;
+ private final AsyncResponse asyncResponse;
+
+ private CanceledRequest(String id, AsyncResponse asyncResponse) {
+ this.id = id;
+ this.asyncResponse = asyncResponse;
+ }
+ }
+
+ /**
+ * Get the async "Hello World" message.
+ */
+ @GET
+ @Produces("text/plain")
+ public void get(@Suspended final AsyncResponse ar) {
+ Executors.newSingleThreadExecutor().execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(100);
+ ar.resume(HELLO_ASYNC_WORLD);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Get a canceled request.
+ *
+ * @param id request id.
+ * @throws InterruptedException in case of not being able to put the request
+ * to an internal queue for canceling.
+ */
+ @GET
+ @Path("canceled")
+ public void getCanceled(@Suspended final AsyncResponse ar, @QueryParam("id") final String id) throws InterruptedException {
+ cancelingQueue.put(new CanceledRequest(id, ar));
+ }
+
+ /**
+ * Cancel a request that is on top of the canceling queue.
+ *
+ * @return notification message about successful request canceling.
+ * @throws InterruptedException in case of not being able to take a cancelled request
+ * from an internal canceling queue.
+ */
+ @POST
+ @Produces("text/plain")
+ @Path("canceled")
+ public String cancel(String requestId) throws InterruptedException {
+ final CanceledRequest canceledRequest = cancelingQueue.take();
+ canceledRequest.asyncResponse.cancel();
+
+ return CANCELED + " " + canceledRequest.id + " by POST " + requestId;
+ }
+
+}
diff --git a/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResource.java b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResource.java
new file mode 100644
index 0000000..23c000b
--- /dev/null
+++ b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResource.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.container.TimeoutHandler;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+@Path("timeout")
+public class AsyncTimeoutResource {
+
+ private static final BlockingQueue<AsyncResponse> queue = new ArrayBlockingQueue<AsyncResponse>(1);
+
+ @GET
+ @Path("suspend")
+ public void suspend(@Suspended final AsyncResponse asyncResponse) {
+ queue.add(asyncResponse);
+ }
+
+ @POST
+ @Path("timeout")
+ public void setTimeOut(final Integer millis) throws InterruptedException {
+ final AsyncResponse asyncResponse = queue.take();
+
+ final boolean timeout1 = asyncResponse.setTimeout(millis, TimeUnit.MILLISECONDS);
+ asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+ @Override
+ public void handleTimeout(final AsyncResponse asyncResponse) {
+ final boolean timeout2 = asyncResponse.setTimeout(millis, TimeUnit.MILLISECONDS);
+ asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+ @Override
+ public void handleTimeout(final AsyncResponse asyncResponse) {
+ asyncResponse.resume("timeout1=" + timeout1 + "_timeout2=" + timeout2 + "_handled");
+ asyncResponse.cancel();
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java
new file mode 100644
index 0000000..5787a1d
--- /dev/null
+++ b/tests/integration/servlet-3-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Asynchronous servlet-deployed resource application.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@ApplicationPath("/")
+public class Servlet3Async extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(AsyncServletResource.class);
+ hashSet.add(AsyncTimeoutResource.class);
+ return hashSet;
+ }
+}
diff --git a/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceITCase.java b/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceITCase.java
new file mode 100644
index 0000000..6cdfb9a
--- /dev/null
+++ b/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceITCase.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Asynchronous servlet-deployed resource test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class AsyncServletResourceITCase extends JerseyTest {
+ private static final Logger LOGGER = Logger.getLogger(AsyncServletResourceITCase.class.getName());
+
+ private static class ResponseRecord {
+ final int status;
+ final String message;
+
+ private ResponseRecord(int status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return status + " : \"" + message + '\"';
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Test asynchronous servlet-deployed resource.
+ *
+ * @throws InterruptedException in case the waiting for all requests to complete was interrupted.
+ */
+ @Test
+ public void testAsyncServlet() throws InterruptedException {
+ final WebTarget resourceTarget = target("async");
+ resourceTarget.register(LoggingFeature.class);
+ final String expectedResponse = AsyncServletResource.HELLO_ASYNC_WORLD;
+
+ final int MAX_MESSAGES = 50;
+ final int LATCH_WAIT_TIMEOUT = 10 * getAsyncTimeoutMultiplier();
+ final boolean debugMode = false;
+ final boolean sequentialGet = false;
+ final Object sequentialGetLock = new Object();
+
+ final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+ .setNameFormat("async-resource-test-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .build());
+
+ final Map<Integer, ResponseRecord> getResponses = new ConcurrentHashMap<Integer, ResponseRecord>();
+
+ final CountDownLatch getRequestLatch = new CountDownLatch(MAX_MESSAGES);
+
+ try {
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ final int requestId = i;
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialGet) {
+ synchronized (sequentialGetLock) {
+ get();
+ }
+ } else {
+ get();
+ }
+ }
+
+ private void get() {
+ try {
+ final Response response = resourceTarget.request().get();
+ getResponses.put(
+ requestId,
+ new ResponseRecord(response.getStatus(), response.readEntity(String.class)));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ getRequestLatch.countDown();
+ }
+ }
+ });
+ }
+
+ //noinspection ConstantConditions
+ if (debugMode) {
+ getRequestLatch.await();
+ } else {
+ assertTrue("Waiting for all GET requests to complete has timed out.", getRequestLatch.await(LATCH_WAIT_TIMEOUT,
+ TimeUnit.SECONDS));
+ }
+ } finally {
+ executor.shutdownNow();
+ }
+
+ StringBuilder messageBuilder = new StringBuilder();
+ for (Map.Entry<Integer, ResponseRecord> getResponseEntry : getResponses.entrySet()) {
+ messageBuilder.append("GET response for message ")
+ .append(getResponseEntry.getKey()).append(": ")
+ .append(getResponseEntry.getValue().toString()).append('\n');
+ }
+ LOGGER.info(messageBuilder.toString());
+
+ assertEquals(MAX_MESSAGES, getResponses.size());
+ for (Map.Entry<Integer, ResponseRecord> entry : getResponses.entrySet()) {
+ assertEquals(
+ "Unexpected GET response status for request " + entry.getKey(),
+ 200, entry.getValue().status);
+ assertEquals(
+ "Unexpected GET response message for request " + entry.getKey(),
+ expectedResponse, entry.getValue().message);
+ }
+ }
+
+ /**
+ * Test canceling of an async request to a servlet-deployed resource.
+ *
+ * @throws InterruptedException in case the waiting for all requests to complete was interrupted.
+ */
+ @Test
+ public void testAsyncRequestCanceling() throws InterruptedException {
+ final WebTarget resourceTarget = target("async/canceled");
+ resourceTarget.register(LoggingFeature.class);
+
+ final int MAX_MESSAGES = 10;
+ final int LATCH_WAIT_TIMEOUT = 10 * getAsyncTimeoutMultiplier();
+ final boolean debugMode = false;
+ final boolean sequentialGet = false;
+ final boolean sequentialPost = false;
+ final Object sequentialGetLock = new Object();
+ final Object sequentialPostLock = new Object();
+
+ final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+ .setNameFormat("async-canceled-resource-test-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .build());
+
+ final Map<Integer, String> postResponses = new ConcurrentHashMap<Integer, String>();
+ final Map<Integer, String> getResponses = new ConcurrentHashMap<Integer, String>();
+
+ final CountDownLatch postRequestLatch = new CountDownLatch(MAX_MESSAGES);
+ final CountDownLatch getRequestLatch = new CountDownLatch(MAX_MESSAGES);
+
+ try {
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ final int requestId = i;
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialGet) {
+ synchronized (sequentialGetLock) {
+ get();
+ }
+ } else {
+ get();
+ }
+ }
+
+ private void get() {
+ try {
+ final String response = resourceTarget.queryParam("id", requestId).request().get(String.class);
+ getResponses.put(requestId, response);
+ } catch (WebApplicationException ex) {
+ final Response response = ex.getResponse();
+ getResponses.put(requestId, response.getStatus() + ": " + response.readEntity(String.class));
+ } finally {
+ getRequestLatch.countDown();
+ }
+ }
+ });
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialPost) {
+ synchronized (sequentialPostLock) {
+ post();
+ }
+ } else {
+ post();
+ }
+ }
+
+ private void post() throws ProcessingException {
+ try {
+ final String response = resourceTarget.request().post(Entity.text("" + requestId), String.class);
+ postResponses.put(requestId, response);
+ } finally {
+ postRequestLatch.countDown();
+ }
+ }
+ });
+ }
+
+ //noinspection ConstantConditions
+ if (debugMode) {
+ postRequestLatch.await();
+ getRequestLatch.await();
+ } else {
+ assertTrue("Waiting for all POST requests to complete has timed out.",
+ postRequestLatch.await(LATCH_WAIT_TIMEOUT, TimeUnit.SECONDS));
+ assertTrue("Waiting for all GET requests to complete has timed out.", getRequestLatch.await(LATCH_WAIT_TIMEOUT,
+ TimeUnit.SECONDS));
+ }
+ } finally {
+ executor.shutdownNow();
+ }
+
+ StringBuilder messageBuilder = new StringBuilder();
+ for (Map.Entry<Integer, String> postResponseEntry : postResponses.entrySet()) {
+ messageBuilder.append("POST response for message ")
+ .append(postResponseEntry.getKey()).append(": ")
+ .append(postResponseEntry.getValue()).append('\n');
+ }
+ messageBuilder.append('\n');
+ for (Map.Entry<Integer, String> getResponseEntry : getResponses.entrySet()) {
+ messageBuilder.append("GET response for message ")
+ .append(getResponseEntry.getKey()).append(": ")
+ .append(getResponseEntry.getValue()).append('\n');
+ }
+ LOGGER.info(messageBuilder.toString());
+
+ assertEquals(MAX_MESSAGES, postResponses.size());
+ for (Map.Entry<Integer, String> postResponseEntry : postResponses.entrySet()) {
+ assertTrue("Unexpected POST notification response for message " + postResponseEntry.getKey(),
+ postResponseEntry.getValue().startsWith(AsyncServletResource.CANCELED));
+ }
+
+ assertEquals(MAX_MESSAGES, getResponses.size());
+ final Collection<Integer> getResponseKeys = getResponses.keySet();
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ assertTrue("Detected a GET message response loss: " + i, getResponseKeys.contains(i));
+ final String getResponseEntry = getResponses.get(i);
+ assertTrue("Unexpected canceled GET response status for request " + i,
+ getResponseEntry.startsWith("503: "));
+ }
+ }
+}
diff --git a/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResourceITCase.java b/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResourceITCase.java
new file mode 100644
index 0000000..8bfb646
--- /dev/null
+++ b/tests/integration/servlet-3-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncTimeoutResourceITCase.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.Future;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+public class AsyncTimeoutResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testTimeout() throws Exception {
+ final WebTarget resourceTarget = target("timeout");
+ resourceTarget.register(LoggingFeature.class);
+ final Future<Response> responseFuture = resourceTarget.path("suspend").request().async().get();
+
+ // Set timeout.
+ assertThat(resourceTarget.path("timeout").request().post(Entity.text("500")).getStatus(), equalTo(204));
+
+ // Wait for it.
+ assertThat(responseFuture.get().readEntity(String.class), equalTo("timeout1=true_timeout2=true_handled"));
+ }
+}
diff --git a/tests/integration/servlet-3-chunked-io/pom.xml b/tests/integration/servlet-3-chunked-io/pom.xml
new file mode 100644
index 0000000..4caa4b5
--- /dev/null
+++ b/tests/integration/servlet-3-chunked-io/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-chunked-io</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-chunked-io</name>
+
+ <description>Servlet integration test - servlet-3-chunked-io</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/App.java b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/App.java
new file mode 100644
index 0000000..2495c51
--- /dev/null
+++ b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/App.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_chunked_io;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.ext.ContextResolver;
+
+import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Chunked I/O test JAX-RS application class.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@ApplicationPath("resources")
+public class App extends ResourceConfig {
+
+ /**
+ * Chunked I/O test JAX-RS application.
+ */
+ public App() {
+ super(TestResource.class);
+
+ register(createMoxyJsonResolver());
+ }
+
+ /**
+ * Create MOXy JSON config context resolver.
+ *
+ * @return new MOXy JSON config context resolver.
+ */
+ public static ContextResolver<MoxyJsonConfig> createMoxyJsonResolver() {
+ final Map<String, String> namespacePrefixMapper = new HashMap<>(1);
+ namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+
+ return new MoxyJsonConfig()
+ .setNamespacePrefixMapper(namespacePrefixMapper)
+ .setNamespaceSeparator(':')
+ .resolver();
+ }
+
+}
diff --git a/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/Message.java b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/Message.java
new file mode 100644
index 0000000..e8b3304
--- /dev/null
+++ b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/Message.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_chunked_io;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Message POJO.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Message {
+
+ /**
+ * Message id.
+ */
+ public int id;
+ /**
+ * Message content.
+ */
+ public String data;
+
+ /**
+ * Create new message.
+ */
+ public Message() {
+ this.id = -1;
+ this.data = "";
+ }
+
+ /**
+ * Create new message.
+ * @param id message id.
+ * @param data message content.
+ */
+ public Message(int id, String data) {
+ if (data == null) {
+ throw new IllegalArgumentException("Message data must not be null.");
+ }
+
+ this.id = id;
+ this.data = data;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Message message = (Message) o;
+
+ if (id != message.id) {
+ return false;
+ }
+ if (!data.equals(message.data)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id;
+ result = 31 * result + data.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "{\"id\":" + id + ",\"data\":\"" + data + "\"}";
+ }
+}
diff --git a/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/TestResource.java b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/TestResource.java
new file mode 100644
index 0000000..6069a99
--- /dev/null
+++ b/tests/integration/servlet-3-chunked-io/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/TestResource.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_chunked_io;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.server.ChunkedOutput;
+
+/**
+ * Test resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("/test")
+public class TestResource {
+
+ private static final Logger LOGGER = Logger.getLogger(TestResource.class.getName());
+
+ /**
+ * Get chunk stream of JSON data - from JSON POJOs.
+ *
+ * @return chunk stream.
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("from-pojo")
+ public ChunkedOutput<Message> getFromPojo() {
+ final ChunkedOutput<Message> output = new ChunkedOutput<>(Message.class, "\r\n");
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 3; i++) {
+ output.write(new Message(i, "test"));
+ Thread.sleep(200);
+ }
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, "Error writing chunk.", e);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, "Sleep interrupted.", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ try {
+ output.close();
+ } catch (final IOException e) {
+ LOGGER.log(Level.INFO, "Error closing chunked output.", e);
+ }
+ }
+ }
+ }.start();
+
+ return output;
+ }
+
+ /**
+ * Get chunk stream of JSON data - from string.
+ *
+ * @return chunk stream.
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("from-string")
+ public ChunkedOutput<String> getFromText() {
+ final ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 3; i++) {
+ output.write(new Message(i, "test").toString() + "\r\n");
+ Thread.sleep(200);
+ }
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, "Error writing chunk.", e);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, "Sleep interrupted.", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ try {
+ output.close();
+ } catch (final IOException e) {
+ LOGGER.log(Level.INFO, "Error closing chunked output.", e);
+ }
+ }
+ }
+ }.start();
+
+ return output;
+ }
+
+ /**
+ * {@link org.glassfish.jersey.server.ChunkedOutput#close()} is called before method returns it's entity. Resource reproduces
+ * JERSEY-2558 issue.
+ *
+ * @return (closed) chunk stream.
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("close-before-return")
+ public ChunkedOutput<Message> closeBeforeReturn() {
+ final ChunkedOutput<Message> output = new ChunkedOutput<>(Message.class, "\r\n");
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 3; i++) {
+ output.write(new Message(i, "test"));
+ Thread.sleep(200);
+ }
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, "Error writing chunk.", e);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, "Sleep interrupted.", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ try {
+ output.close();
+ // Worker thread can continue.
+ latch.countDown();
+ } catch (final IOException e) {
+ LOGGER.log(Level.INFO, "Error closing chunked output.", e);
+ }
+ }
+ }
+ }.start();
+
+ try {
+ // Wait till new thread closes the chunked output.
+ latch.await();
+ return output;
+ } catch (final InterruptedException e) {
+ throw new InternalServerErrorException(e);
+ }
+ }
+
+ /**
+ * Test combination of AsyncResponse and ChunkedOutput.
+ *
+ * @param response async response.
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("chunked-async")
+ public void closeBeforeReturnAsync(@Suspended final AsyncResponse response) {
+ // Set timeout to able to resume but not send the chunks (setting the ChunkedOutput should remove the timeout).
+ response.setTimeout(1500, TimeUnit.SECONDS);
+
+ new Thread() {
+
+ @Override
+ public void run() {
+ final ChunkedOutput<Message> output = new ChunkedOutput<>(Message.class, "\r\n");
+
+ try {
+ // Let the method return.
+ Thread.sleep(1000);
+ // Resume.
+ response.resume(output);
+ // Wait for resume to complete.
+ Thread.sleep(1000);
+
+ new Thread() {
+
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 3; i++) {
+ output.write(new Message(i, "test"));
+ Thread.sleep(200);
+ }
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, "Error writing chunk.", e);
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, "Sleep interrupted.", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ try {
+ output.close();
+ } catch (final IOException e) {
+ LOGGER.log(Level.INFO, "Error closing chunked output.", e);
+ }
+ }
+ }
+ }.start();
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, "Sleep interrupted.", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }.start();
+ }
+}
diff --git a/tests/integration/servlet-3-chunked-io/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/ChunkedInputOutputITCase.java b/tests/integration/servlet-3-chunked-io/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/ChunkedInputOutputITCase.java
new file mode 100644
index 0000000..40d57af
--- /dev/null
+++ b/tests/integration/servlet-3-chunked-io/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_chunked_io/ChunkedInputOutputITCase.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_chunked_io;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URLConnection;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ChunkedInput;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Chunked I/O integration tests.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class ChunkedInputOutputITCase extends JerseyTest {
+
+ private static final int MAX_LISTENERS = 5;
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(App.createMoxyJsonResolver());
+
+ config.property(ClientProperties.CONNECT_TIMEOUT, 15000)
+ .property(ClientProperties.READ_TIMEOUT, 5000)
+ .property(ClientProperties.ASYNC_THREADPOOL_SIZE, MAX_LISTENERS + 1)
+ .connectorProvider(new GrizzlyConnectorProvider());
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ final UriBuilder baseUriBuilder = UriBuilder.fromUri(super.getBaseUri());
+ final boolean externalFactoryInUse = getTestContainerFactory() instanceof ExternalTestContainerFactory;
+ return externalFactoryInUse ? baseUriBuilder.path("resources").build() : baseUriBuilder.build();
+ }
+
+ /**
+ * Test retrieving string-based chunked stream as a single response string.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testChunkedOutputToSingleString() throws Exception {
+ final String response = target().path("test/from-string").request(MediaType.APPLICATION_JSON_TYPE).get(String.class);
+
+ assertEquals("Unexpected value of chunked response unmarshalled as a single string.",
+ "{\"id\":0,\"data\":\"test\"}\r\n"
+ + "{\"id\":1,\"data\":\"test\"}\r\n"
+ + "{\"id\":2,\"data\":\"test\"}\r\n",
+ response);
+ }
+
+ /**
+ * Test retrieving string-based chunked stream sequentially as individual chunks using chunked input.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testChunkedOutputToChunkInputFromString() throws Exception {
+ final ChunkedInput<Message> input = target().path("test/from-string").request(MediaType.APPLICATION_JSON_TYPE)
+ .get(new GenericType<ChunkedInput<Message>>() {
+ });
+
+ int counter = 0;
+ Message chunk;
+ while ((chunk = input.read()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, new Message(counter, "test"), chunk);
+ counter++;
+ }
+
+ assertEquals("Unexpected numbed of received chunks.", 3, counter);
+ }
+
+ /**
+ * Test retrieving POJO-based chunked stream sequentially as individual chunks using chunked input.
+ *
+ * @throws Exception in case of a failure during the test execution.
+ */
+ @Test
+ public void testChunkedOutputToChunkInputFromPojo() throws Exception {
+ final ChunkedInput<Message> input = target().path("test/from-pojo").request(MediaType.APPLICATION_JSON_TYPE)
+ .get(new GenericType<ChunkedInput<Message>>() {
+ });
+
+ int counter = 0;
+ Message chunk;
+ while ((chunk = input.read()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, new Message(counter, "test"), chunk);
+ counter++;
+ }
+
+ assertEquals("Unexpected numbed of received chunks.", 3, counter);
+ }
+
+ /**
+ * Test combination of AsyncResponse and ChunkedOutput.
+ */
+ @Test
+ public void chunkedOutputWithAsyncResponse() throws Exception {
+ final ChunkedInput<Message> input = target().path("test/chunked-async").request(MediaType.APPLICATION_JSON_TYPE)
+ .get(new GenericType<ChunkedInput<Message>>() {
+ });
+
+ int counter = 0;
+ Message chunk;
+ while ((chunk = input.read()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, new Message(counter, "test"), chunk);
+ counter++;
+ }
+
+ assertEquals("Unexpected numbed of received chunks.", 3, counter);
+ }
+
+ /**
+ * Reproducer for JERSEY-2558. Checking that the connection is properly closed even when the
+ * {@link org.glassfish.jersey.server.ChunkedOutput#close()} is called before the response is processed by the runtime.
+ */
+ @Test
+ public void checkConnectionIsClosedUrlConnection() throws Exception {
+ final URI uri = UriBuilder.fromUri(super.getBaseUri()).path("test/close-before-return").build();
+ final URLConnection connection = uri.toURL().openConnection();
+
+ connection.setConnectTimeout(15000);
+ connection.setReadTimeout(15000);
+ connection.connect();
+
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+
+ String line;
+ int counter = 0;
+ while ((line = reader.readLine()) != null) {
+ assertEquals("Unexpected value of chunk " + counter, new Message(counter, "test").toString(), line);
+ counter++;
+ }
+
+ assertEquals("Unexpected numbed of received chunks.", 3, counter);
+ }
+}
diff --git a/tests/integration/servlet-3-filter/pom.xml b/tests/integration/servlet-3-filter/pom.xml
new file mode 100644
index 0000000..1bbe427
--- /dev/null
+++ b/tests/integration/servlet-3-filter/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-filter</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-filter</name>
+
+ <description>Servlet integration test - servlet-3-filter</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResource.java b/tests/integration/servlet-3-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResource.java
new file mode 100644
index 0000000..ca3c3a7
--- /dev/null
+++ b/tests/integration/servlet-3-filter/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_filter;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Path("myresource")
+public class MyResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "OK";
+ }
+}
diff --git a/tests/integration/servlet-3-filter/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3dcf4e4
--- /dev/null
+++ b/tests/integration/servlet-3-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <filter>
+ <filter-name>Jersey Web Application</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_3_filter</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>Jersey Web Application</filter-name>
+ <url-pattern>/myapp/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResourceITCase.java b/tests/integration/servlet-3-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResourceITCase.java
new file mode 100644
index 0000000..226ac74
--- /dev/null
+++ b/tests/integration/servlet-3-filter/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_filter/MyResourceITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_filter;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MyResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig rc = new ResourceConfig();
+ return rc.packages(MyResourceITCase.class.getPackage().getName());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testMyResource() throws Exception {
+ final Response response = target().path("myapp").path("myresource").request().get();
+ assertEquals(200, response.getStatus());
+ assertEquals("OK", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testWadl() {
+ final Response response = target().path("myapp/application.wadl").request().get();
+ assertEquals(200, response.getStatus());
+ assertTrue(response.readEntity(String.class).startsWith("<?xml version=\"1.0\""));
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/pom.xml b/tests/integration/servlet-3-gf-async/pom.xml
new file mode 100644
index 0000000..9d53935
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-gf-async</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-gf-async</name>
+
+ <description>Servlet (GF) integration test - servlet-3-gf-async - configured via jax-rs application annotated with @javax.ws.rs.ApplicationPath</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <systemPropertyVariables>
+ <jersey.config.test.container.factory>${testContainerFactory}</jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${testContainerPort}</jersey.config.test.container.port>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <skipTests>true</skipTests>
+ <testContainerFactory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</testContainerFactory>
+ <testContainerPort>8080</testContainerPort>
+ </properties>
+</project>
diff --git a/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResource.java b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResource.java
new file mode 100644
index 0000000..f67f854
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResource.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.container.TimeoutHandler;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+@Path("cancel-timeout")
+public class AsyncCancelTimeoutResource {
+
+ @SuppressWarnings("unchecked")
+ private static final BlockingQueue<AsyncResponse>[] stages = new BlockingQueue[]{
+ new ArrayBlockingQueue<AsyncResponse>(1),
+ new ArrayBlockingQueue<AsyncResponse>(1)
+ };
+
+ @GET
+ @Path("suspend")
+ public void suspend(@Suspended final AsyncResponse asyncResponse) {
+ stages[0].add(asyncResponse);
+ }
+
+ @POST
+ @Path("timeout")
+ public void setTimeout(final String stage) throws Exception {
+ final AsyncResponse async = stages[Integer.parseInt(stage)].take();
+
+ async.setTimeoutHandler(new TimeoutHandler() {
+ @Override
+ public void handleTimeout(final AsyncResponse response) {
+ response.cancel();
+ }
+ });
+ async.setTimeout(200L, TimeUnit.MILLISECONDS);
+
+ stages[Integer.parseInt(stage) + 1].add(async);
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResource.java b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResource.java
new file mode 100644
index 0000000..e6ad2dc
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.container.TimeoutHandler;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+@Path("resume-timeout")
+public class AsyncResumeTimeoutResource {
+
+ private static final BlockingQueue<AsyncResponse> queue = new ArrayBlockingQueue<>(1);
+
+ @GET
+ @Path("suspend")
+ public void suspend(@Suspended final AsyncResponse asyncResponse) {
+ queue.add(asyncResponse);
+ }
+
+ @POST
+ @Path("timeout")
+ public void setTimeOut(final Integer millis) throws InterruptedException {
+ final AsyncResponse asyncResponse = queue.take();
+
+ final boolean timeout1 = asyncResponse.setTimeout(millis, TimeUnit.MILLISECONDS);
+ asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+ @Override
+ public void handleTimeout(final AsyncResponse asyncResponse) {
+ final boolean timeout2 = asyncResponse.setTimeout(millis, TimeUnit.MILLISECONDS);
+ asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+ @Override
+ public void handleTimeout(final AsyncResponse asyncResponse) {
+ asyncResponse.resume("timeout1=" + timeout1 + "_timeout2=" + timeout2 + "_handled");
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java
new file mode 100644
index 0000000..3cd45ec
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+/**
+ * Asynchronous servlet-deployed resource.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("async")
+public class AsyncServletResource {
+ /**
+ * Hello world message.
+ */
+ public static final String HELLO_ASYNC_WORLD = "Hello Async World!";
+ public static final String CANCELED = "Canceled";
+
+ private static BlockingQueue<CanceledRequest> cancelingQueue = new ArrayBlockingQueue<CanceledRequest>(5);
+
+ private static class CanceledRequest {
+ private final String id;
+ private final AsyncResponse asyncResponse;
+
+ private CanceledRequest(final String id, final AsyncResponse asyncResponse) {
+ this.id = id;
+ this.asyncResponse = asyncResponse;
+ }
+ }
+
+ /**
+ * Get the async "Hello World" message.
+ */
+ @GET
+ @Produces("text/plain")
+ public void get(@Suspended final AsyncResponse ar) {
+ Executors.newSingleThreadExecutor().execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(100);
+ ar.resume(HELLO_ASYNC_WORLD);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Get a canceled request.
+ *
+ * @param id request id.
+ * @throws InterruptedException in case of not being able to put the request
+ * to an internal queue for canceling.
+ */
+ @GET
+ @Path("canceled")
+ public void getCanceled(@Suspended final AsyncResponse ar, @QueryParam("id") final String id) throws InterruptedException {
+ cancelingQueue.put(new CanceledRequest(id, ar));
+ }
+
+ /**
+ * Cancel a request that is on top of the canceling queue.
+ *
+ * @return notification message about successful request canceling.
+ * @throws InterruptedException in case of not being able to take a cancelled request
+ * from an internal canceling queue.
+ */
+ @POST
+ @Produces("text/plain")
+ @Path("canceled")
+ public String cancel(final String requestId) throws InterruptedException {
+ final CanceledRequest canceledRequest = cancelingQueue.take();
+ canceledRequest.asyncResponse.cancel();
+
+ return CANCELED + " " + canceledRequest.id + " by POST " + requestId;
+ }
+
+}
diff --git a/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java
new file mode 100644
index 0000000..c0be482
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_async/Servlet3Async.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Asynchronous servlet-deployed resource application.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@ApplicationPath("/")
+public class Servlet3Async extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<>();
+ hashSet.add(AsyncServletResource.class);
+ hashSet.add(AsyncResumeTimeoutResource.class);
+ hashSet.add(AsyncCancelTimeoutResource.class);
+ return hashSet;
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResourceTest.java b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResourceTest.java
new file mode 100644
index 0000000..5735317
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncCancelTimeoutResourceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.Future;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+public class AsyncCancelTimeoutResourceTest extends JerseyTest {
+
+ public AsyncCancelTimeoutResourceTest() {
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return ServletDeploymentContext.builder(new Application())
+ .contextPath("servlet-3-gf-async")
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testTimeout() throws Exception {
+ final WebTarget resourceTarget = target("cancel-timeout");
+ final Future<Response> suspend = resourceTarget.path("suspend").request().async().get();
+ final Future<Response> timeout = resourceTarget.path("timeout").request().async().post(Entity.text(0));
+
+ assertThat(timeout.get().getStatus(), is(Response.Status.NO_CONTENT.getStatusCode()));
+ assertThat(suspend.get().getStatus(), is(Response.Status.SERVICE_UNAVAILABLE.getStatusCode()));
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResourceTest.java b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResourceTest.java
new file mode 100644
index 0000000..a40976a
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncResumeTimeoutResourceTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.concurrent.Future;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Asynchronous servlet-deployed resource for testing {@link javax.ws.rs.container.AsyncResponse async response} timeouts.
+ *
+ * @author Michal Gajdos
+ */
+public class AsyncResumeTimeoutResourceTest extends JerseyTest {
+
+ public AsyncResumeTimeoutResourceTest() {
+ enable(TestProperties.LOG_TRAFFIC);
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return ServletDeploymentContext.builder(new Application())
+ .contextPath("servlet-3-gf-async")
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testTimeout() throws Exception {
+ final WebTarget resourceTarget = target("resume-timeout");
+ final Future<Response> responseFuture = resourceTarget.path("suspend").request().async().get();
+
+ // Set timeout.
+ assertThat(resourceTarget.path("timeout").request().post(Entity.text("500")).getStatus(), equalTo(204));
+
+ // Wait for it.
+ assertThat(responseFuture.get().readEntity(String.class), equalTo("timeout1=true_timeout2=true_handled"));
+ }
+}
diff --git a/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceTest.java b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceTest.java
new file mode 100644
index 0000000..69ac18f
--- /dev/null
+++ b/tests/integration/servlet-3-gf-async/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_async/AsyncServletResourceTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_async;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Asynchronous servlet-deployed resource test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+public class AsyncServletResourceTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(AsyncServletResourceTest.class.getName());
+
+ private static class ResponseRecord {
+
+ final int status;
+ final String message;
+
+ private ResponseRecord(final int status, final String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return status + " : \"" + message + '\"';
+ }
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return ServletDeploymentContext.builder(new Application())
+ .contextPath("servlet-3-gf-async")
+ .build();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ /**
+ * Test asynchronous servlet-deployed resource.
+ *
+ * @throws InterruptedException in case the waiting for all requests to complete was interrupted.
+ */
+ @Test
+ public void testAsyncServlet() throws InterruptedException {
+ final WebTarget resourceTarget = target("async");
+ resourceTarget.register(LoggingFeature.class);
+ final String expectedResponse = AsyncServletResource.HELLO_ASYNC_WORLD;
+
+ final int MAX_MESSAGES = 50;
+ final int LATCH_WAIT_TIMEOUT = 10;
+ final boolean debugMode = false;
+ final boolean sequentialGet = false;
+ final Object sequentialGetLock = new Object();
+
+ final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+ .setNameFormat("async-resource-test-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .build());
+
+ final Map<Integer, ResponseRecord> getResponses = new ConcurrentHashMap<>();
+
+ final CountDownLatch getRequestLatch = new CountDownLatch(MAX_MESSAGES);
+
+ try {
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ final int requestId = i;
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialGet) {
+ synchronized (sequentialGetLock) {
+ get();
+ }
+ } else {
+ get();
+ }
+ }
+
+ private void get() {
+ try {
+ final Response response = resourceTarget.request().get();
+ getResponses.put(requestId, new ResponseRecord(response.getStatus(),
+ response.readEntity(String.class)));
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ } finally {
+ getRequestLatch.countDown();
+ }
+ }
+ });
+ }
+
+ //noinspection ConstantConditions
+ if (debugMode) {
+ getRequestLatch.await();
+ } else {
+ assertTrue("Waiting for all GET requests to complete has timed out.",
+ getRequestLatch.await(LATCH_WAIT_TIMEOUT * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS));
+ }
+ } finally {
+ executor.shutdownNow();
+ }
+
+ final StringBuilder messageBuilder = new StringBuilder();
+ for (final Map.Entry<Integer, ResponseRecord> getResponseEntry : getResponses.entrySet()) {
+ messageBuilder.append("GET response for message ").append(getResponseEntry.getKey()).append(": ")
+ .append(getResponseEntry.getValue().toString()).append('\n');
+ }
+ LOGGER.info(messageBuilder.toString());
+
+ assertEquals(MAX_MESSAGES, getResponses.size());
+ for (final Map.Entry<Integer, ResponseRecord> entry : getResponses.entrySet()) {
+ assertEquals("Unexpected GET response status for request " + entry.getKey(), 200, entry.getValue().status);
+ assertEquals("Unexpected GET response message for request " + entry.getKey(), expectedResponse,
+ entry.getValue().message);
+ }
+ }
+
+ /**
+ * Test canceling of an async request to a servlet-deployed resource.
+ *
+ * @throws InterruptedException in case the waiting for all requests to complete was interrupted.
+ */
+ @Test
+ public void testAsyncRequestCanceling() throws InterruptedException {
+ final WebTarget resourceTarget = target("async/canceled");
+ resourceTarget.register(LoggingFeature.class);
+
+ final int MAX_MESSAGES = 10;
+ final int LATCH_WAIT_TIMEOUT = 10;
+ final boolean debugMode = false;
+ final boolean sequentialGet = false;
+ final boolean sequentialPost = false;
+ final Object sequentialGetLock = new Object();
+ final Object sequentialPostLock = new Object();
+
+ final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+ .setNameFormat("async-canceled-resource-test-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .build());
+
+ final Map<Integer, String> postResponses = new ConcurrentHashMap<>();
+ final Map<Integer, String> getResponses = new ConcurrentHashMap<>();
+
+ final CountDownLatch postRequestLatch = new CountDownLatch(MAX_MESSAGES);
+ final CountDownLatch getRequestLatch = new CountDownLatch(MAX_MESSAGES);
+
+ try {
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ final int requestId = i;
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialGet) {
+ synchronized (sequentialGetLock) {
+ get();
+ }
+ } else {
+ get();
+ }
+ }
+
+ private void get() {
+ try {
+ final String response = resourceTarget.queryParam("id", requestId).request().get(String.class);
+ getResponses.put(requestId, response);
+ } catch (final WebApplicationException ex) {
+ final Response response = ex.getResponse();
+ getResponses.put(requestId, response.getStatus() + ": " + response.readEntity(String.class));
+ } finally {
+ getRequestLatch.countDown();
+ }
+ }
+ });
+ executor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (debugMode || sequentialPost) {
+ synchronized (sequentialPostLock) {
+ post();
+ }
+ } else {
+ post();
+ }
+ }
+
+ private void post() throws ProcessingException {
+ try {
+ final String response = resourceTarget.request().post(Entity.text("" + requestId), String.class);
+ postResponses.put(requestId, response);
+ } finally {
+ postRequestLatch.countDown();
+ }
+ }
+ });
+ }
+
+ //noinspection ConstantConditions
+ if (debugMode) {
+ postRequestLatch.await();
+ getRequestLatch.await();
+ } else {
+ assertTrue("Waiting for all POST requests to complete has timed out.",
+ postRequestLatch.await(LATCH_WAIT_TIMEOUT * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS));
+ assertTrue("Waiting for all GET requests to complete has timed out.",
+ getRequestLatch.await(LATCH_WAIT_TIMEOUT * getAsyncTimeoutMultiplier(),
+ TimeUnit.SECONDS));
+ }
+ } finally {
+ executor.shutdownNow();
+ }
+
+ final StringBuilder messageBuilder = new StringBuilder();
+ for (final Map.Entry<Integer, String> postResponseEntry : postResponses.entrySet()) {
+ messageBuilder.append("POST response for message ").append(postResponseEntry.getKey()).append(": ")
+ .append(postResponseEntry.getValue()).append('\n');
+ }
+ messageBuilder.append('\n');
+ for (final Map.Entry<Integer, String> getResponseEntry : getResponses.entrySet()) {
+ messageBuilder.append("GET response for message ").append(getResponseEntry.getKey()).append(": ")
+ .append(getResponseEntry.getValue()).append('\n');
+ }
+ LOGGER.info(messageBuilder.toString());
+
+ assertEquals(MAX_MESSAGES, postResponses.size());
+ for (final Map.Entry<Integer, String> postResponseEntry : postResponses.entrySet()) {
+ assertTrue("Unexpected POST notification response for message " + postResponseEntry.getKey(),
+ postResponseEntry.getValue().startsWith(AsyncServletResource.CANCELED));
+ }
+
+ assertEquals(MAX_MESSAGES, getResponses.size());
+ final Collection<Integer> getResponseKeys = getResponses.keySet();
+ for (int i = 0; i < MAX_MESSAGES; i++) {
+ assertTrue("Detected a GET message response loss: " + i, getResponseKeys.contains(i));
+ final String getResponseEntry = getResponses.get(i);
+ assertTrue("Unexpected canceled GET response status for request " + i, getResponseEntry.startsWith("503: "));
+ }
+ }
+}
diff --git a/tests/integration/servlet-3-inflector-1/pom.xml b/tests/integration/servlet-3-inflector-1/pom.xml
new file mode 100644
index 0000000..312ec21
--- /dev/null
+++ b/tests/integration/servlet-3-inflector-1/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-inflector-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-inflector-1</name>
+
+ <description>
+ Servlet integration test - servlet-3-inflector-1 - Check that inflectors in programmatically created resources are
+ properly injected.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyApplication.java b/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyApplication.java
new file mode 100644
index 0000000..7c7a797
--- /dev/null
+++ b/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_inflector_1;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+
+/**
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/")
+public class MyApplication extends ResourceConfig {
+
+ public MyApplication() {
+ final Resource.Builder resourceBuilder = Resource.builder("resource");
+
+ resourceBuilder.addChildResource("class")
+ .addMethod("GET")
+ .handledBy(MyInflector.class);
+ resourceBuilder.addChildResource("instance")
+ .addMethod("GET")
+ .handledBy(new MyInflector());
+
+ registerResources(resourceBuilder.build());
+ }
+}
diff --git a/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyInflector.java b/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyInflector.java
new file mode 100644
index 0000000..7315a7d
--- /dev/null
+++ b/tests/integration/servlet-3-inflector-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/MyInflector.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_inflector_1;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.process.Inflector;
+
+/**
+ * @author Michal Gajdos
+ */
+public class MyInflector implements Inflector<ContainerRequestContext, Response> {
+
+ @Inject
+ private Provider<HttpServletRequest> requestProvider;
+ @Inject
+ private Provider<HttpServletResponse> responseProvider;
+
+ @Override
+ public Response apply(final ContainerRequestContext requestContext) {
+ final StringBuilder stringBuilder = new StringBuilder();
+
+ // Request provider & request.
+ if (requestProvider != null) {
+ stringBuilder.append("requestProvider_");
+ stringBuilder.append(requestProvider.get() != null ? "request" : null);
+ } else {
+ stringBuilder.append("null_null");
+ }
+
+ stringBuilder.append('_');
+
+ // Response provider & response.
+ if (responseProvider != null) {
+ stringBuilder.append("responseProvider_");
+ stringBuilder.append(responseProvider.get() != null ? "response" : null);
+ } else {
+ stringBuilder.append("null_null");
+ }
+
+ return Response.ok(stringBuilder.toString()).build();
+ }
+}
diff --git a/tests/integration/servlet-3-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/InflectorInjectionTestITCase.java b/tests/integration/servlet-3-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/InflectorInjectionTestITCase.java
new file mode 100644
index 0000000..4dff377
--- /dev/null
+++ b/tests/integration/servlet-3-inflector-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_inflector_1/InflectorInjectionTestITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_inflector_1;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class InflectorInjectionTestITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new MyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInflectorClassInjection() throws Exception {
+ _testInflectorInjection("class");
+ }
+
+ @Test
+ public void testInflectorInstanceInjection() throws Exception {
+ _testInflectorInjection("instance");
+ }
+
+ private void _testInflectorInjection(final String path) {
+ final Response response = target("resource").path(path).request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals("requestProvider_request_responseProvider_response", response.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-3-init-1/pom.xml b/tests/integration/servlet-3-init-1/pom.xml
new file mode 100644
index 0000000..b0a1d04
--- /dev/null
+++ b/tests/integration/servlet-3-init-1/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-1</name>
+
+ <description>Servlet integration test - servlet-3-init-1 - configured via jax-rs application annotated with @javax.ws.rs.ApplicationPath</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResource.java b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResource.java
new file mode 100644
index 0000000..ea4d55f
--- /dev/null
+++ b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_1;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/Servlet3init1.java b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/Servlet3init1.java
new file mode 100644
index 0000000..13b7c88
--- /dev/null
+++ b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/Servlet3init1.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_1;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@ApplicationPath("/")
+public class Servlet3init1 extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(HelloWorldResource.class);
+ return hashSet;
+ }
+}
diff --git a/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/UnreachableResource.java b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/UnreachableResource.java
new file mode 100644
index 0000000..5251265
--- /dev/null
+++ b/tests/integration/servlet-3-init-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/UnreachableResource.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_1;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Martin Matula
+ */
+@Path("unreachable")
+public class UnreachableResource {
+ @GET
+ public Response get() {
+ return Response.ok().build();
+ }
+}
diff --git a/tests/integration/servlet-3-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..b2edbf7
--- /dev/null
+++ b/tests/integration/servlet-3-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_1/HelloWorldResourceITCase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_1;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Martin Matula
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ WebTarget t = target();
+ t.register(LoggingFeature.class);
+ Response r = t.path("helloworld").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("Hello World!", r.readEntity(String.class));
+ }
+
+ @Test
+ public void testUnreachableResource() {
+ Response r = target().path("unreachable").request().get();
+ assertEquals("Managed to reach a resource that is not registered in the application.", 404, r.getStatus());
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/pom.xml b/tests/integration/servlet-3-init-2/pom.xml
new file mode 100644
index 0000000..0b37d39
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-2</name>
+
+ <description>
+ Servlet integration test - servlet-3-init-2 - configured via jax-rs application annotated with @javax.ws.rs.ApplicationPath
+ and providers annotated with @javax.ws.rs.ext.Provider.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/CustomFeature.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/CustomFeature.java
new file mode 100644
index 0000000..e36c557
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/CustomFeature.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.tests.integration.servlet_3_init_2.ext.Ext1WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_3_init_2.ext.Ext2WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_3_init_2.ext.Ext3WriterInterceptor;
+import org.glassfish.jersey.tests.integration.servlet_3_init_2.ext.Ext4WriterInterceptor;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class CustomFeature implements Feature {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(Ext3WriterInterceptor.class, 1000);
+ context.register(Ext2WriterInterceptor.class, 100);
+ context.register(Ext1WriterInterceptor.INSTANCE, 500);
+ context.register(Ext4WriterInterceptor.INSTANCE, 1);
+ return true;
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResource.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResource.java
new file mode 100644
index 0000000..27b3797
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/Servlet3init2.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/Servlet3init2.java
new file mode 100644
index 0000000..011254f
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/Servlet3init2.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/")
+public class Servlet3init2 extends ResourceConfig {
+
+ public Servlet3init2() {
+ packages(false, Servlet3init2.class.getPackage().getName());
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext1WriterInterceptor.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext1WriterInterceptor.java
new file mode 100644
index 0000000..84e4b05
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext1WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext1WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext1WriterInterceptor INSTANCE = new Ext1WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext1");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext2WriterInterceptor.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext2WriterInterceptor.java
new file mode 100644
index 0000000..2bc9a05
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext2WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext2WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext2");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext3WriterInterceptor.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext3WriterInterceptor.java
new file mode 100644
index 0000000..802b1bb
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext3WriterInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext3WriterInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext3");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext4WriterInterceptor.java b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext4WriterInterceptor.java
new file mode 100644
index 0000000..77bb734
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/ext/Ext4WriterInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2.ext;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Michal Gajdos
+ */
+@Provider
+public class Ext4WriterInterceptor implements WriterInterceptor {
+
+ public static final Ext4WriterInterceptor INSTANCE = new Ext4WriterInterceptor();
+
+ @Override
+ public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.setEntity(context.getEntity() + "-ext4");
+ context.proceed();
+ }
+}
diff --git a/tests/integration/servlet-3-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..c0fbdb0
--- /dev/null
+++ b/tests/integration/servlet-3-init-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_2/HelloWorldResourceITCase.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_2;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Martin Matula
+ * @author Michal Gajdos
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ Response r = target().path("helloworld").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("Hello World!-ext4-ext2-ext1-ext3", r.readEntity(String.class));
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-3/pom.xml b/tests/integration/servlet-3-init-3/pom.xml
new file mode 100644
index 0000000..71ea462
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-3</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-3</name>
+
+ <description>Servlet integration test - servlet-3-init-3 - both Application.getClasses and Application.getSingletons return an empty collection</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplication.java b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplication.java
new file mode 100644
index 0000000..e4f3783
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplication.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_3;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyApplication extends Application {
+}
diff --git a/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceOne.java b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceOne.java
new file mode 100644
index 0000000..a31e39a
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceOne.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_3.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("one")
+public class ResourceOne {
+
+ @GET
+ public String get() {
+ return ResourceOne.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceTwo.java b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceTwo.java
new file mode 100644
index 0000000..e6ce245
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/resource/ResourceTwo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_3.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("two")
+public class ResourceTwo {
+
+ @GET
+ public String get() {
+ return ResourceTwo.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-3/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-3/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c1ed518
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_3.EmptyApplication</servlet-name>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_3.EmptyApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplicationTestITCase.java b/tests/integration/servlet-3-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplicationTestITCase.java
new file mode 100644
index 0000000..f762576
--- /dev/null
+++ b/tests/integration/servlet-3-init-3/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_3/EmptyApplicationTestITCase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_3;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.servlet_3_init_3.resource.ResourceOne;
+import org.glassfish.jersey.tests.integration.servlet_3_init_3.resource.ResourceTwo;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyApplicationTestITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new EmptyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceOne() throws Exception {
+ final Response response = target("one").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ResourceOne.class.getSimpleName(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceTwo() throws Exception {
+ final Response response = target("two").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ResourceTwo.class.getSimpleName(), response.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-3-init-4/pom.xml b/tests/integration/servlet-3-init-4/pom.xml
new file mode 100644
index 0000000..470666d
--- /dev/null
+++ b/tests/integration/servlet-3-init-4/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-4</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-4</name>
+
+ <description>
+ Servlet integration test - servlet-3-init-4 - both Application.getClasses and Application.getSingletons return an empty
+ collection, @ApplicationPath present
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplication.java b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplication.java
new file mode 100644
index 0000000..5a2042a
--- /dev/null
+++ b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplication.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_4;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+@ApplicationPath("/")
+public class EmptyApplication extends Application {
+}
diff --git a/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceOne.java b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceOne.java
new file mode 100644
index 0000000..f43e50c
--- /dev/null
+++ b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceOne.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_4.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("one")
+public class ResourceOne {
+
+ @GET
+ public String get() {
+ return ResourceOne.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceTwo.java b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceTwo.java
new file mode 100644
index 0000000..45e9de4
--- /dev/null
+++ b/tests/integration/servlet-3-init-4/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/resource/ResourceTwo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_4.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("two")
+public class ResourceTwo {
+
+ @GET
+ public String get() {
+ return ResourceTwo.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplicationTestITCase.java b/tests/integration/servlet-3-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplicationTestITCase.java
new file mode 100644
index 0000000..4c3b2b6
--- /dev/null
+++ b/tests/integration/servlet-3-init-4/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_4/EmptyApplicationTestITCase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_4;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.servlet_3_init_4.resource.ResourceOne;
+import org.glassfish.jersey.tests.integration.servlet_3_init_4.resource.ResourceTwo;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyApplicationTestITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new EmptyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceOne() throws Exception {
+ final Response response = target("one").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ResourceOne.class.getSimpleName(), response.readEntity(String.class));
+ }
+
+ @Test
+ public void testResourceTwo() throws Exception {
+ final Response response = target("two").request().get();
+
+ assertEquals(200, response.getStatus());
+ assertEquals(ResourceTwo.class.getSimpleName(), response.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-3-init-5/pom.xml b/tests/integration/servlet-3-init-5/pom.xml
new file mode 100644
index 0000000..e96aac6
--- /dev/null
+++ b/tests/integration/servlet-3-init-5/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-5</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-5</name>
+
+ <description>Servlet integration test - servlet-3-init-5 - no Application subclass is present;
+ dynamically add a servlet and set its name to javax.ws.rs.core.Application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResource.java b/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResource.java
new file mode 100644
index 0000000..91d8093
--- /dev/null
+++ b/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_5;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public Hello get() {
+ return new Hello();
+ }
+
+ public static class Hello {
+
+ }
+}
diff --git a/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWriter.java b/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWriter.java
new file mode 100644
index 0000000..d70573a
--- /dev/null
+++ b/tests/integration/servlet-3-init-5/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWriter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_5;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class HelloWriter implements MessageBodyWriter<HelloWorldResource.Hello> {
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(HelloWorldResource.Hello.class);
+ }
+
+ @Override
+ public long getSize(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ entityStream.write(("Hello World! " + this.getClass().getPackage().getName())
+ .getBytes(MessageUtils.getCharset(mediaType)));
+ }
+}
diff --git a/tests/integration/servlet-3-init-5/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-5/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..520cb3e
--- /dev/null
+++ b/tests/integration/servlet-3-init-5/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..af14376
--- /dev/null
+++ b/tests/integration/servlet-3-init-5/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_5/HelloWorldResourceITCase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_5;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-3-init-6/pom.xml b/tests/integration/servlet-3-init-6/pom.xml
new file mode 100644
index 0000000..709c875
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-6</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-6</name>
+
+ <description>Servlet integration test - servlet-3-init-5 - Application subclass is present;
+ servlet-mapping in web.xml</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplication.java b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplication.java
new file mode 100644
index 0000000..760f1c5
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplication.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_6;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyApplication extends Application {
+}
diff --git a/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceOne.java b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceOne.java
new file mode 100644
index 0000000..a4da8ea
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceOne.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_6.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("one")
+public class ResourceOne {
+
+ @GET
+ public String get() {
+ return ResourceOne.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceTwo.java b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceTwo.java
new file mode 100644
index 0000000..8d4e270
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/resource/ResourceTwo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_6.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("two")
+public class ResourceTwo {
+
+ @GET
+ public String get() {
+ return ResourceTwo.class.getSimpleName();
+ }
+}
diff --git a/tests/integration/servlet-3-init-6/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-6/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d5bf156
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_6.EmptyApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_6.EmptyApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplicationITCase.java b/tests/integration/servlet-3-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplicationITCase.java
new file mode 100644
index 0000000..c85d8bb
--- /dev/null
+++ b/tests/integration/servlet-3-init-6/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_6/EmptyApplicationITCase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_6;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.servlet_3_init_6.resource.ResourceOne;
+import org.glassfish.jersey.tests.integration.servlet_3_init_6.resource.ResourceTwo;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class EmptyApplicationITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new EmptyApplication();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceOne() throws Exception {
+ final Response response = target("one").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ResourceOne.class.getSimpleName()));
+ }
+
+ @Test
+ public void testResourceTwo() throws Exception {
+ final Response response = target("two").request().get();
+
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.readEntity(String.class), is(ResourceTwo.class.getSimpleName()));
+ }
+}
diff --git a/tests/integration/servlet-3-init-7/pom.xml b/tests/integration/servlet-3-init-7/pom.xml
new file mode 100644
index 0000000..30869d5
--- /dev/null
+++ b/tests/integration/servlet-3-init-7/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-7</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-7</name>
+
+ <description>Servlet integration test - servlet-3-init-7 - no Application subclass is present;
+ dynamically add a servlet and set its name to javax.ws.rs.core.Application;
+ servlet-mapping in web.xml</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResource.java b/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResource.java
new file mode 100644
index 0000000..acaaf92
--- /dev/null
+++ b/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_7;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld")
+public class HelloWorldResource {
+
+ @GET
+ @Produces("text/plain")
+ public Hello get() {
+ return new Hello();
+ }
+
+ public static class Hello {
+
+ }
+}
diff --git a/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWriter.java b/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWriter.java
new file mode 100644
index 0000000..3e9898f
--- /dev/null
+++ b/tests/integration/servlet-3-init-7/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWriter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_7;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class HelloWriter implements MessageBodyWriter<HelloWorldResource.Hello> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(HelloWorldResource.Hello.class);
+ }
+
+ @Override
+ public long getSize(final HelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final HelloWorldResource.Hello hello,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ entityStream.write(("Hello World! " + this.getClass().getPackage().getName()).getBytes());
+ }
+}
diff --git a/tests/integration/servlet-3-init-7/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-7/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c87f441
--- /dev/null
+++ b/tests/integration/servlet-3-init-7/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..43f36e3
--- /dev/null
+++ b/tests/integration/servlet-3-init-7/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_7/HelloWorldResourceITCase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_7;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(HelloWorldResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ String s = target().path("helloworld").request().get(String.class);
+ assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName()));
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/pom.xml b/tests/integration/servlet-3-init-8/pom.xml
new file mode 100644
index 0000000..094fcfa
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-8</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-8</name>
+
+ <description>Servlet integration test - servlet-3-init-8 - more jax-rs applications
+ (annotated with @javax.ws.rs.ApplicationPath and/or configured in web.xml).
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld1Resource.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld1Resource.java
new file mode 100644
index 0000000..5604139
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld1Resource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld1")
+public class HelloWorld1Resource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World 1!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld2Resource.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld2Resource.java
new file mode 100644
index 0000000..cba1bdd
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld2Resource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld2")
+public class HelloWorld2Resource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World 2!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld3Resource.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld3Resource.java
new file mode 100644
index 0000000..010ae62
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld3Resource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld3")
+public class HelloWorld3Resource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World 3!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld4Resource.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld4Resource.java
new file mode 100644
index 0000000..82936a1
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorld4Resource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld4")
+public class HelloWorld4Resource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello World 4!";
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App1.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App1.java
new file mode 100644
index 0000000..e32c718
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App1.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * The application is fully configured in {@code web.xml} ({@code servlet} as well as {@code servlet-mapping}).
+ * It means {@code ApplicationPath.value} ({@code /app1ann}) is overridden using a {@code servlet-mapping} element.
+ * The application also explicitly register JAX-RS resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/app1ann")
+public class Servlet3Init8App1 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<>();
+ hashSet.add(HelloWorld1Resource.class);
+ return hashSet;
+ }
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App2.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App2.java
new file mode 100644
index 0000000..1ca6ecf
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App2.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * The application is partially configured in {@code web.xml} (just {@code servlet} element).
+ * It means {@code ApplicationPath.value} ({@code /app2ann}) is used as base servlet URI.
+ * The application also explicitly register JAX-RS resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/app2ann")
+public class Servlet3Init8App2 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<>();
+ hashSet.add(HelloWorld2Resource.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App3.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App3.java
new file mode 100644
index 0000000..c7163e1
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App3.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * The application is not configured in {@code web.xml}.
+ * It means {@code ApplicationPath.value} ({@code /app3ann}) is used as base servlet URI.
+ * The application also explicitly register JAX-RS resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/app3ann")
+public class Servlet3Init8App3 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<>();
+ hashSet.add(HelloWorld3Resource.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App4.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App4.java
new file mode 100644
index 0000000..9a3667c
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App4.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * The application is fully configured in {@code web.xml} ({@code servlet} as well as {@code servlet-mapping}).
+ * And there is no {@code ApplicationPath} annotation on the class.
+ * The application also explicitly register JAX-RS resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Servlet3Init8App4 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<>();
+ hashSet.add(HelloWorld4Resource.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App5.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App5.java
new file mode 100644
index 0000000..b1f2ea8
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/Servlet3Init8App5.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * The application is fully configured in {@code web.xml} ({@code servlet} as well as {@code servlet-mapping}).
+ * And there is no {@code ApplicationPath} annotation on the class.
+ * The application does NOT explicitly register any JAX-RS resource. All available resources are automatically registered.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Servlet3Init8App5 extends Application {
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/UnreachableResource.java b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/UnreachableResource.java
new file mode 100644
index 0000000..99f9710
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/UnreachableResource.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("unreachable")
+public class UnreachableResource {
+
+ @GET
+ @Produces("text/plain")
+ public String get() {
+ return "Hello Unreachable!";
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-8/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d5c3a63
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App1</servlet-name>
+ <url-pattern>/app1/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App2</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App4</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App4</servlet-name>
+ <url-pattern>/app4/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App5</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_8.Servlet3Init8App5</servlet-name>
+ <url-pattern>/app5/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceITCase.java
new file mode 100644
index 0000000..0955681
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceITCase.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test reachable resources.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class HelloWorldResourceITCase extends JerseyTest {
+
+ private final String appPath;
+ private final String resourcePath;
+ private final String helloName;
+
+ public HelloWorldResourceITCase(String appPath, String resourcePath, String helloName) {
+ this.appPath = appPath;
+ this.resourcePath = resourcePath;
+ this.helloName = helloName;
+ }
+
+ @Parameterized.Parameters(name = "{index}: {0}/{1} \"{2}\"")
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"/app1", "helloworld1", "World 1"}, //app1 - overridden using a servlet-mapping element in the web.xml
+ {"/app2ann", "helloworld2", "World 2"}, //app2ann - no servlet-mapping in the web.xml, used ApplicationPath.value
+ {"/app3ann", "helloworld3", "World 3"}, //app3ann - no servlet in the web.xml, used ApplicationPath.value
+ {"/app4", "helloworld4", "World 4"}, //app4 - fully configured in web.xml
+ //app5 - automatic registration of all resources, no explicit classes/singletons provided by Servlet3Init8App5
+ {"/app5", "helloworld1", "World 1"},
+ {"/app5", "helloworld2", "World 2"},
+ {"/app5", "helloworld3", "World 3"},
+ {"/app5", "helloworld4", "World 4"},
+ {"/app5", "unreachable", "Unreachable"},
+ });
+ }
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ WebTarget t = target(appPath);
+ t.register(LoggingFeature.class);
+ Response r = t.path(resourcePath).request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("Hello " + helloName + "!", r.readEntity(String.class));
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceUnreachableITCase.java b/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceUnreachableITCase.java
new file mode 100644
index 0000000..914687d
--- /dev/null
+++ b/tests/integration/servlet-3-init-8/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_8/HelloWorldResourceUnreachableITCase.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_8;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test unreachable resources.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class HelloWorldResourceUnreachableITCase extends JerseyTest {
+
+ private final String appPath;
+ private final String resourcePath;
+
+ public HelloWorldResourceUnreachableITCase(String appPath,
+ String resourcePath) {
+ this.appPath = appPath;
+ this.resourcePath = resourcePath;
+ }
+
+ @Parameterized.Parameters(name = "{index}: {0}/{1}")
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"/app1", "unreachable"}, //unreachable - no explicitly mentioned resource
+ {"/app1ann", "helloworld1"}, //app1ann - overridden using a servlet-mapping element in the web.xml
+ {"/app2ann", "unreachable"}, //unreachable - no explicitly mentioned resource
+ {"/app3ann", "unreachable"}, //unreachable - no explicitly mentioned resource
+ {"/app4", "unreachable"}, //unreachable - no explicitly mentioned resource
+ });
+ }
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testUnreachableResource() {
+ WebTarget t = target(appPath);
+ t.register(LoggingFeature.class);
+ Response r = t.path(resourcePath).request().get();
+ assertEquals(404, r.getStatus());
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/pom.xml b/tests/integration/servlet-3-init-provider/pom.xml
new file mode 100644
index 0000000..75417cb
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-init-provider</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-init-provider</name>
+
+ <description>Servlet integration test - servlet-3-init-provider - ServletContainerProviderFactory, ServletContainerProvider</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-servlet-portability</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResource.java
new file mode 100644
index 0000000..489a50b
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public abstract class AbstractHelloWorldResource {
+
+ public static final int NUMBER_OF_APPLICATIONS = 5;
+
+ @GET
+ @Produces("text/plain")
+ public Hello get() {
+ return new Hello(createName());
+ }
+
+ protected abstract String createName();
+
+
+ public static class Hello {
+ private final String name;
+
+ public Hello(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application1.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application1.java
new file mode 100644
index 0000000..8316b40
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application1.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Application1 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(HelloWorld1Resource.class);
+ hashSet.add(HelloWriter.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application2.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application2.java
new file mode 100644
index 0000000..89f1683
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application2.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Application2 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(HelloWorld2Resource.class);
+ hashSet.add(HelloWriter.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application3.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application3.java
new file mode 100644
index 0000000..20932c5
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application3.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Application3 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(HelloWorld3Resource.class);
+ hashSet.add(HelloWriter.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application4.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application4.java
new file mode 100644
index 0000000..e89767d
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/Application4.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/application4/*")
+public class Application4 extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> hashSet = new HashSet<Class<?>>();
+ hashSet.add(HelloWorld4Resource.class);
+ hashSet.add(HelloWriter.class);
+ return hashSet;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1Resource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1Resource.java
new file mode 100644
index 0000000..9ffd315
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1Resource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld1")
+public class HelloWorld1Resource extends AbstractHelloWorldResource {
+
+ @Override
+ protected String createName() {
+ return "World #1";
+ }
+
+ @GET
+ @Path("servlets")
+ public int getServletsCount() {
+ return TestServletContainerProvider.getServletNames().size();
+ }
+
+ @GET
+ @Path("servlets/{name}")
+ public boolean hasServletName(@PathParam("name") String servletName) {
+ return TestServletContainerProvider.getServletNames().contains(servletName);
+ }
+
+ @GET
+ @Path("immutableServletNames")
+ public boolean isImmutableServletNames() {
+ return TestServletContainerProvider.isImmutableServletNames();
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2Resource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2Resource.java
new file mode 100644
index 0000000..99cc572
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.Path;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld2")
+public class HelloWorld2Resource extends AbstractHelloWorldResource {
+
+ @Override
+ protected String createName() {
+ return "World #2";
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3Resource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3Resource.java
new file mode 100644
index 0000000..9f510e0
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3Resource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld3")
+public class HelloWorld3Resource extends AbstractHelloWorldResource {
+
+ @Override
+ protected String createName() {
+ return "World #3";
+ }
+
+ @GET
+ @Path("containers")
+ public int getContainersCount() throws InterruptedException {
+ return TestContainerLifecycleListener.getStartupCount();
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4Resource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4Resource.java
new file mode 100644
index 0000000..f8db2e3
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4Resource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.Path;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld4")
+public class HelloWorld4Resource extends AbstractHelloWorldResource {
+
+ @Override
+ protected String createName() {
+ return "World #4";
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5Resource.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5Resource.java
new file mode 100644
index 0000000..aa8350a
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5Resource.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import java.util.Enumeration;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("helloworld5")
+public class HelloWorld5Resource extends AbstractHelloWorldResource {
+
+ @Context
+ private HttpServletRequest request;
+
+ @Override
+ protected String createName() {
+ return "World #5";
+ }
+
+ @GET
+ @Path("filter")
+ public String getFilter() {
+ return (String) request.getAttribute("FILTER");
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWriter.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWriter.java
new file mode 100644
index 0000000..cb061cd
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWriter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class HelloWriter implements MessageBodyWriter<AbstractHelloWorldResource.Hello> {
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(AbstractHelloWorldResource.Hello.class);
+ }
+
+ @Override
+ public long getSize(final AbstractHelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final AbstractHelloWorldResource.Hello hello, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ final String value = String.format("Hello %s!", hello.getName());
+ entityStream.write(value.getBytes(MessageUtils.getCharset(mediaType)));
+ }
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestContainerLifecycleListener.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestContainerLifecycleListener.java
new file mode 100644
index 0000000..e8a1b0e
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestContainerLifecycleListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.ContainerLifecycleListener;
+
+/**
+ * This is just test purpose implementation of Jersey SPI {@link ContainerLifecycleListener}.
+ * The listener class is registered in {@link TestServletContainerProvider} to {@link ResourceConfig}.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TestContainerLifecycleListener implements ContainerLifecycleListener {
+
+ private static int startupCount = 0;
+
+ private static CountDownLatch latch = new CountDownLatch(AbstractHelloWorldResource.NUMBER_OF_APPLICATIONS);
+
+ @Override
+ public void onStartup(Container container) {
+ latch.countDown();
+ startupCount++;
+ }
+
+ @Override
+ public void onReload(Container container) {
+ }
+
+ @Override
+ public void onShutdown(Container container) {
+ }
+
+ public static int getStartupCount() throws InterruptedException {
+ latch.await(5, TimeUnit.SECONDS);
+ return startupCount;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestFilter.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestFilter.java
new file mode 100644
index 0000000..27093c3
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestFilter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This is just test purpose {@link Filter servlet filter} implementation to demonstrate how to register filter for any Jersey
+ * Servlet.
+ * The filter class is added in {@link TestServletContainerProvider}.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TestFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ if (((HttpServletRequest) request).getRequestURI().startsWith("/application5")) {
+ request.setAttribute("FILTER", TestServletContainerProvider.TEST_FILTER);
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestServletContainerProvider.java b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestServletContainerProvider.java
new file mode 100644
index 0000000..abe1a50
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/TestServletContainerProvider.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.servlet.internal.spi.RequestScopedInitializerProvider;
+import org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider;
+
+/**
+ * This is just test purpose implementation of Jersey internal SPI {@link ServletContainerProvider}.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TestServletContainerProvider implements ServletContainerProvider {
+
+ public static final String TEST_FILTER = "TestFilter";
+
+ private static Set<String> SERVLET_NAMES;
+ private static boolean immutableServletNames = false;
+
+ @Override
+ public void preInit(final ServletContext servletContext, final Set<Class<?>> classes) throws ServletException {
+ classes.add(AbstractHelloWorldResource.class);
+ }
+
+ @Override
+ public void postInit(final ServletContext servletContext, final Set<Class<?>> classes, final Set<String> servletNames)
+ throws ServletException {
+ try {
+ servletNames.add("TEST");
+ } catch (final UnsupportedOperationException ex) {
+ TestServletContainerProvider.setImmutableServletNames(true);
+ }
+ }
+
+ @Override
+ public void onRegister(final ServletContext servletContext, final Set<String> servletNames) throws ServletException {
+ TestServletContainerProvider.setServletNames(servletNames);
+
+ servletContext.addFilter(TEST_FILTER, TestFilter.class)
+ .addMappingForServletNames(EnumSet.allOf(DispatcherType.class), false,
+ servletNames.toArray(new String[servletNames.size()]));
+ }
+
+ @Override
+ public void configure(final ResourceConfig resourceConfig) throws ServletException {
+ if (!resourceConfig.isRegistered(TestContainerLifecycleListener.class)) {
+ resourceConfig.register(TestContainerLifecycleListener.class);
+ }
+ }
+
+ public static Set<String> getServletNames() {
+ return SERVLET_NAMES;
+ }
+
+ public static boolean isImmutableServletNames() {
+ return immutableServletNames;
+ }
+
+ private static void setServletNames(final Set<String> servletNames) {
+ TestServletContainerProvider.SERVLET_NAMES = servletNames;
+ }
+
+ public static void setImmutableServletNames(final boolean immutableServletNames) {
+ TestServletContainerProvider.immutableServletNames = immutableServletNames;
+ }
+}
diff --git a/tests/integration/servlet-3-init-provider/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider b/tests/integration/servlet-3-init-provider/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
new file mode 100644
index 0000000..14fedce
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.servlet_3_init_provider.TestServletContainerProvider
\ No newline at end of file
diff --git a/tests/integration/servlet-3-init-provider/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-provider/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..aa1f9ea
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application1</servlet-name>
+ </servlet>
+ <servlet>
+ <servlet-name>application2</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application2</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet>
+ <servlet-name>application3</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.portability.PortableServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey2#javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application3</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_3_init_provider.HelloWorld5Resource,
+ org.glassfish.jersey.tests.integration.servlet_3_init_provider.HelloWriter
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application1</servlet-name>
+ <url-pattern>/application1/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>application2</servlet-name>
+ <url-pattern>/application2/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>application3</servlet-name>
+ <url-pattern>/application3/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>javax.ws.rs.core.Application</servlet-name>
+ <url-pattern>/application5/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResourceTest.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResourceTest.java
new file mode 100644
index 0000000..fec1830
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/AbstractHelloWorldResourceTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import org.junit.Assert;
+
+import javax.ws.rs.NotFoundException;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public abstract class AbstractHelloWorldResourceTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new ResourceConfig(getResourceClass());
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ for (int i = 1; i <= AbstractHelloWorldResource.NUMBER_OF_APPLICATIONS; i++) {
+ try {
+ String actual = target("application" + getIndex()).path("helloworld" + i).request().get(String.class);
+ if (i == getIndex()) {
+ Assert.assertEquals("Hello World #" + getIndex() + "!", actual);
+ } else {
+ Assert.fail("i: " + i + " | [" + actual + "]");
+ }
+ } catch (NotFoundException ex) {
+ if (i != getIndex()) {
+ Assert.assertEquals(404, ex.getResponse().getStatus());
+ } else {
+ Assert.fail("!!! i: " + i);
+ }
+ }
+ }
+ }
+
+ protected abstract Class<?> getResourceClass();
+
+ protected abstract int getIndex();
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1ResourceITCase.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1ResourceITCase.java
new file mode 100644
index 0000000..1299390
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld1ResourceITCase.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorld1ResourceITCase extends AbstractHelloWorldResourceTest {
+
+ protected Class<?> getResourceClass() {
+ return HelloWorld1Resource.class;
+ }
+
+ protected int getIndex() {
+ return 1;
+ }
+
+ @Test
+ public void testRegisteredServletNames() throws Exception {
+ WebTarget target = target("application" + getIndex()).path("helloworld" + getIndex()).path("servlets");
+ Assert.assertEquals(AbstractHelloWorldResource.NUMBER_OF_APPLICATIONS, (int) target.request().get(Integer.TYPE));
+
+ target = target.path("{name}");
+ testRegisteredServletNames(target, "org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application1");
+ testRegisteredServletNames(target, "application2");
+ testRegisteredServletNames(target, "application3");
+ testRegisteredServletNames(target, "org.glassfish.jersey.tests.integration.servlet_3_init_provider.Application4");
+ testRegisteredServletNames(target, "javax.ws.rs.core.Application");
+ }
+
+ private void testRegisteredServletNames(WebTarget target, String servletName) throws Exception {
+ Assert.assertTrue(target.resolveTemplate("name", servletName).request().get(Boolean.TYPE));
+ }
+
+ @Test
+ public void testImmutableServletNames() {
+ WebTarget target = target("application" + getIndex()).path("helloworld" + getIndex()).path("immutableServletNames");
+ Assert.assertTrue(target.request().get(Boolean.TYPE));
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2ResourceITCase.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2ResourceITCase.java
new file mode 100644
index 0000000..e38ac59
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld2ResourceITCase.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorld2ResourceITCase extends AbstractHelloWorldResourceTest {
+
+ protected Class<?> getResourceClass() {
+ return HelloWorld2Resource.class;
+ }
+
+ protected int getIndex() {
+ return 2;
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3ResourceITCase.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3ResourceITCase.java
new file mode 100644
index 0000000..6a16e46
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld3ResourceITCase.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.ws.rs.client.WebTarget;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorld3ResourceITCase extends AbstractHelloWorldResourceTest {
+
+ protected Class<?> getResourceClass() {
+ return HelloWorld3Resource.class;
+ }
+
+ protected int getIndex() {
+ return 3;
+ }
+
+ @Test
+ public void testStartupContainers() throws Exception {
+ WebTarget target = target("application" + getIndex()).path("helloworld" + getIndex()).path("containers");
+ Assert.assertEquals(AbstractHelloWorldResource.NUMBER_OF_APPLICATIONS, (int) target.request().get(Integer.TYPE));
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4ResourceITCase.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4ResourceITCase.java
new file mode 100644
index 0000000..9d39e25
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld4ResourceITCase.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorld4ResourceITCase extends AbstractHelloWorldResourceTest {
+
+ protected Class<?> getResourceClass() {
+ return HelloWorld4Resource.class;
+ }
+
+ protected int getIndex() {
+ return 4;
+ }
+
+ @Test
+ public void testRegisterFilter() throws Exception {
+ Response response = target("application" + getIndex()).path("helloworld" + getIndex()).path("filter").request().get();
+ Assert.assertEquals(404, response.getStatus());
+ }
+
+}
diff --git a/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5ResourceITCase.java b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5ResourceITCase.java
new file mode 100644
index 0000000..81dae7b
--- /dev/null
+++ b/tests/integration/servlet-3-init-provider/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_provider/HelloWorld5ResourceITCase.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_init_provider;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class HelloWorld5ResourceITCase extends AbstractHelloWorldResourceTest {
+
+ protected Class<?> getResourceClass() {
+ return HelloWorld5Resource.class;
+ }
+
+ protected int getIndex() {
+ return 5;
+ }
+
+ @Test
+ public void testRegisterFilter() throws Exception {
+ String actual = target("application" + getIndex()).path("helloworld" + getIndex()).path("filter").request()
+ .get(String.class);
+ Assert.assertEquals(TestServletContainerProvider.TEST_FILTER, actual);
+ }
+
+}
diff --git a/tests/integration/servlet-3-params/pom.xml b/tests/integration/servlet-3-params/pom.xml
new file mode 100644
index 0000000..c0a5ceb
--- /dev/null
+++ b/tests/integration/servlet-3-params/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-params</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-params</name>
+
+ <description>Servlet integration test - servlet-3-params</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/CustomContextListener.java b/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/CustomContextListener.java
new file mode 100644
index 0000000..82a54c8
--- /dev/null
+++ b/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/CustomContextListener.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_params;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@WebListener
+public class CustomContextListener implements ServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent servletContextEvent) {
+ servletContextEvent.getServletContext().setAttribute("myContextParam", "myValue");
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent servletContextEvent) {
+
+ }
+}
+
diff --git a/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamResource.java b/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamResource.java
new file mode 100644
index 0000000..79ef7a8
--- /dev/null
+++ b/tests/integration/servlet-3-params/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_params;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+@Path("params")
+public class ParamResource {
+
+ @Context
+ Application application;
+
+ @GET
+ @Produces("text/plain")
+ public String get(@QueryParam("param-name") String paramName) {
+ return application.getProperties().get(paramName).toString();
+ }
+}
diff --git a/tests/integration/servlet-3-params/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-params/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1f118a7
--- /dev/null
+++ b/tests/integration/servlet-3-params/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>testServlet1</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_3_params.ParamResource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>myInitParam</param-name>
+ <param-value>myValue</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet1</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-3-params/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamsTestITCase.java b/tests/integration/servlet-3-params/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamsTestITCase.java
new file mode 100644
index 0000000..5dc4151
--- /dev/null
+++ b/tests/integration/servlet-3-params/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_params/ParamsTestITCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_params;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Pavel Bucek (pavel.bucek at oracle.com)
+ */
+public class ParamsTestITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ // see web.xml
+ @Test
+ public void testInitParam() throws Exception {
+ Response r = target().path("params").queryParam("param-name", "myInitParam").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("myValue", r.readEntity(String.class));
+ }
+
+ // see CustomContextListener.java
+ @Test
+ public void testContextParam() throws Exception {
+ Response r = target().path("params").queryParam("param-name", "myContextParam").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("myValue", r.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/servlet-3-sse-1/pom.xml b/tests/integration/servlet-3-sse-1/pom.xml
new file mode 100644
index 0000000..d7ea408
--- /dev/null
+++ b/tests/integration/servlet-3-sse-1/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-3-sse-1</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-3-sse-1</name>
+
+ <description>Servlet integration test - servlet-3-sse-1</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <!--plugin>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>0</scanIntervalSeconds>
+ <stopPort>9999</stopPort>
+ <stopKey>STOP</stopKey>
+ <contextPath>/</contextPath>
+ <webApp>
+ <contextPath>/</contextPath>
+ </webApp>
+ <war>${project.build.directory}/${project.build.finalName}.war</war>
+ <systemProperties>
+ <systemProperty>
+ <name>jetty.port</name>
+ <value>${jersey.config.test.container.port}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ <executions>
+ <execution>
+ <id>start-jetty</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>run-war</goal>
+ </goals>
+ <configuration>
+ <daemon>true</daemon>
+ </configuration>
+ </execution>
+ <execution>
+ <id>stop-jetty</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin-->
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreApp.java b/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreApp.java
new file mode 100644
index 0000000..3e37025
--- /dev/null
+++ b/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreApp.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_sse_1;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * SSE item store JAX-RS application class.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@ApplicationPath("resources")
+public class ItemStoreApp extends ResourceConfig {
+ /**
+ * Create new SSE Item Store Example JAX-RS application.
+ */
+ public ItemStoreApp() {
+ super(ItemStoreResource.class, SseFeature.class);
+ }
+}
diff --git a/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResource.java b/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResource.java
new file mode 100644
index 0000000..dbbb285
--- /dev/null
+++ b/tests/integration/servlet-3-sse-1/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResource.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_sse_1;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Logger;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.ServiceUnavailableException;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseBroadcaster;
+import org.glassfish.jersey.media.sse.SseFeature;
+
+/**
+ * A resource for storing named items.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Path("items")
+public class ItemStoreResource {
+ private static final Logger LOGGER = Logger.getLogger(ItemStoreResource.class.getName());
+
+ private static final ReentrantReadWriteLock storeLock = new ReentrantReadWriteLock();
+ private static final LinkedList<String> itemStore = new LinkedList<String>();
+ private static final SseBroadcaster broadcaster = new SseBroadcaster();
+
+ private static volatile long reconnectDelay = 0;
+
+ /**
+ * List all stored items.
+ *
+ * @return list of all stored items.
+ */
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String listItems() {
+ try {
+ storeLock.readLock().lock();
+ return itemStore.toString();
+ } finally {
+ storeLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Receive & process commands sent by the test client that control the internal resource state.
+ *
+ * Following is the list of recognized commands:
+ * <ul>
+ * <li><b>disconnect</b> - disconnect all registered event streams.</li>
+ * <li><b>reconnect now</b> - enable client reconnecting.</li>
+ * <li><b>reconnect <seconds></b> - disable client reconnecting.
+ * Reconnecting clients will receive a HTTP 503 response with
+ * {@value javax.ws.rs.core.HttpHeaders#RETRY_AFTER} set to the amount of
+ * milliseconds specified.</li>
+ * </ul>
+ *
+ * @param command command to be processed.
+ * @return message about processing result.
+ * @throws BadRequestException in case the command is not recognized or not specified.
+ */
+ @POST
+ @Path("commands")
+ public String processCommand(String command) {
+ if (command == null || command.isEmpty()) {
+ throw new BadRequestException("No command specified.");
+ }
+
+ if ("disconnect".equals(command)) {
+ broadcaster.closeAll();
+ return "Disconnected.";
+ } else if (command.length() > "reconnect ".length() && command.startsWith("reconnect ")) {
+ final String when = command.substring("reconnect ".length());
+ try {
+ reconnectDelay = "now".equals(when) ? 0 : Long.parseLong(when);
+ return "Reconnect strategy updated: " + when;
+ } catch (NumberFormatException ignore) {
+ // ignored
+ }
+ }
+
+ throw new BadRequestException("Command not recognized: '" + command + "'");
+ }
+
+ /**
+ * Connect or re-connect to SSE event stream.
+ *
+ * @param lastEventId Value of custom SSE HTTP <tt>{@value SseFeature#LAST_EVENT_ID_HEADER}</tt> header.
+ * Defaults to {@code -1} if not set.
+ * @return new SSE event output stream representing the (re-)established SSE client connection.
+ * @throws InternalServerErrorException in case replaying missed events to the reconnected output stream fails.
+ * @throws ServiceUnavailableException in case the reconnect delay is set to a positive value.
+ */
+ @GET
+ @Path("events")
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput itemEvents(
+ @HeaderParam(SseFeature.LAST_EVENT_ID_HEADER) @DefaultValue("-1") int lastEventId) {
+ final EventOutput eventOutput = new EventOutput();
+
+ if (lastEventId >= 0) {
+ LOGGER.info("Received last event id :" + lastEventId);
+
+ // decide the reconnect handling strategy based on current reconnect delay value.
+ final long delay = reconnectDelay;
+ if (delay > 0) {
+ LOGGER.info("Non-zero reconnect delay [" + delay + "] - responding with HTTP 503.");
+ throw new ServiceUnavailableException(delay);
+ } else {
+ LOGGER.info("Zero reconnect delay - reconnecting.");
+ replayMissedEvents(lastEventId, eventOutput);
+ }
+ }
+
+ if (!broadcaster.add(eventOutput)) {
+ LOGGER.severe("!!! Unable to add new event output to the broadcaster !!!");
+ // let's try to force a 5s delayed client reconnect attempt
+ throw new ServiceUnavailableException(5L);
+ }
+
+ return eventOutput;
+ }
+
+ private void replayMissedEvents(final int lastEventId, final EventOutput eventOutput) {
+ try {
+ storeLock.readLock().lock();
+ final int firstUnreceived = lastEventId + 1;
+ final int missingCount = itemStore.size() - firstUnreceived;
+ if (missingCount > 0) {
+ LOGGER.info("Replaying events - starting with id " + firstUnreceived);
+ final ListIterator<String> it = itemStore.subList(firstUnreceived, itemStore.size()).listIterator();
+ while (it.hasNext()) {
+ eventOutput.write(createItemEvent(it.nextIndex() + firstUnreceived, it.next()));
+ }
+ } else {
+ LOGGER.info("No events to replay.");
+ }
+ } catch (IOException ex) {
+ throw new InternalServerErrorException("Error replaying missed events", ex);
+ } finally {
+ storeLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Add new item to the item store.
+ *
+ * Invoking this method will fire 2 new SSE events - 1st about newly added item and 2nd about the new item store size.
+ *
+ * @param name item name.
+ */
+ @POST
+ public void addItem(@FormParam("name") String name) {
+ final int eventId;
+ try {
+ storeLock.writeLock().lock();
+ eventId = itemStore.size();
+ itemStore.add(name);
+ // Broadcasting an un-named event with the name of the newly added item in data
+ broadcaster.broadcast(createItemEvent(eventId, name));
+ // Broadcasting a named "size" event with the current size of the items collection in data
+ broadcaster.broadcast(new OutboundEvent.Builder().name("size").data(Integer.class, eventId + 1).build());
+ } finally {
+ storeLock.writeLock().unlock();
+ }
+ }
+
+ private OutboundEvent createItemEvent(final int eventId, final String name) {
+ Logger.getLogger(ItemStoreResource.class.getName()).info("Creating event id [" + eventId + "] name [" + name + "]");
+ return new OutboundEvent.Builder().id("" + eventId).data(String.class, name).build();
+ }
+}
diff --git a/tests/integration/servlet-3-sse-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResourceITCase.java b/tests/integration/servlet-3-sse-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResourceITCase.java
new file mode 100644
index 0000000..70bdd76
--- /dev/null
+++ b/tests/integration/servlet-3-sse-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_sse_1/ItemStoreResourceITCase.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_3_sse_1;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.media.sse.EventListener;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.describedAs;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Item store test.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Ignore
+public class ItemStoreResourceITCase extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(ItemStoreResourceITCase.class.getName());
+ private static final int MAX_LISTENERS = 5;
+ private static final int MAX_ITEMS = 10;
+
+
+ @Override
+ protected Application configure() {
+ return new ItemStoreApp();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(ClientProperties.CONNECT_TIMEOUT, 15000)
+ .property(ClientProperties.READ_TIMEOUT, 2000)
+ .property(ClientProperties.ASYNC_THREADPOOL_SIZE, MAX_LISTENERS + 1)
+ .connectorProvider(new GrizzlyConnectorProvider());
+ }
+
+ @Override
+ protected URI getBaseUri() {
+ final UriBuilder baseUriBuilder = UriBuilder.fromUri(super.getBaseUri());
+ final boolean externalFactoryInUse = getTestContainerFactory() instanceof ExternalTestContainerFactory;
+ return externalFactoryInUse ? baseUriBuilder.path("resources").build() : baseUriBuilder.build();
+ }
+
+ /**
+ * Test the item addition, addition event broadcasting and item retrieval from {@link ItemStoreResource}.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testItemsStore() throws Exception {
+ final List<String> items = Collections.unmodifiableList(Arrays.asList(
+ "foo",
+ "bar",
+ "baz"));
+ final WebTarget itemsTarget = target("items");
+ final CountDownLatch latch = new CountDownLatch(items.size() * MAX_LISTENERS * 2); // countdown on all events
+ final List<Queue<Integer>> indexQueues = new ArrayList<Queue<Integer>>(MAX_LISTENERS);
+ final EventSource[] sources = new EventSource[MAX_LISTENERS];
+ final AtomicInteger sizeEventsCount = new AtomicInteger(0);
+
+ for (int i = 0; i < MAX_LISTENERS; i++) {
+ final int id = i;
+ final EventSource es = EventSource.target(itemsTarget.path("events"))
+ .named("SOURCE " + id).build();
+ sources[id] = es;
+
+ final Queue<Integer> indexes = new ConcurrentLinkedQueue<Integer>();
+ indexQueues.add(indexes);
+
+ es.register(new EventListener() {
+ @Override
+ @SuppressWarnings("MagicNumber")
+ public void onEvent(InboundEvent inboundEvent) {
+ try {
+ if (inboundEvent.getName() == null) {
+ final String data = inboundEvent.readData();
+ LOGGER.info("[-i-] SOURCE " + id + ": Received event id=" + inboundEvent.getId() + " data=" + data);
+ indexes.add(items.indexOf(data));
+ } else if ("size".equals(inboundEvent.getName())) {
+ sizeEventsCount.incrementAndGet();
+ }
+ } catch (ProcessingException ex) {
+ LOGGER.log(Level.SEVERE, "[-x-] SOURCE " + id + ": Error getting event data.", ex);
+ indexes.add(-999);
+ } finally {
+ latch.countDown();
+ }
+ }
+ });
+ }
+
+ try {
+ open(sources);
+
+ for (String item : items) {
+ postItem(itemsTarget, item);
+ }
+
+ assertTrue("Waiting to receive all events has timed out.",
+ latch.await((1000 + MAX_LISTENERS * EventSource.RECONNECT_DEFAULT) * getAsyncTimeoutMultiplier(),
+ TimeUnit.MILLISECONDS));
+
+ // need to force disconnect on server in order for EventSource.close(...) to succeed with HttpUrlConnection
+ sendCommand(itemsTarget, "disconnect");
+ } finally {
+ close(sources);
+ }
+
+ String postedItems = itemsTarget.request().get(String.class);
+ for (String item : items) {
+ assertTrue("Item '" + item + "' not stored on server.", postedItems.contains(item));
+ }
+
+ int queueId = 0;
+ for (Queue<Integer> indexes : indexQueues) {
+ for (int i = 0; i < items.size(); i++) {
+ assertTrue("Event for '" + items.get(i) + "' not received in queue " + queueId, indexes.contains(i));
+ }
+ assertEquals("Not received the expected number of events in queue " + queueId, items.size(), indexes.size());
+ queueId++;
+ }
+
+ assertEquals("Number of received 'size' events does not match.", items.size() * MAX_LISTENERS, sizeEventsCount.get());
+ }
+
+ /**
+ * Test the {@link EventSource} reconnect feature.
+ *
+ * @throws Exception in case of a test failure.
+ */
+ @Test
+ public void testEventSourceReconnect() throws Exception {
+ final WebTarget itemsTarget = target("items");
+ final CountDownLatch latch = new CountDownLatch(MAX_ITEMS * MAX_LISTENERS * 2); // countdown only on new item events
+ final List<Queue<String>> receivedQueues = new ArrayList<Queue<String>>(MAX_LISTENERS);
+ final EventSource[] sources = new EventSource[MAX_LISTENERS];
+
+ for (int i = 0; i < MAX_LISTENERS; i++) {
+ final int id = i;
+ final EventSource es = EventSource.target(itemsTarget.path("events")).named("SOURCE " + id).build();
+ sources[id] = es;
+
+ final Queue<String> received = new ConcurrentLinkedQueue<String>();
+ receivedQueues.add(received);
+
+ es.register(new EventListener() {
+ @Override
+ public void onEvent(InboundEvent inboundEvent) {
+ try {
+ if (inboundEvent.getName() == null) {
+ latch.countDown();
+ final String data = inboundEvent.readData();
+ LOGGER.info("[-i-] SOURCE " + id + ": Received event id=" + inboundEvent.getId() + " data=" + data);
+ received.add(data);
+ }
+ } catch (ProcessingException ex) {
+ LOGGER.log(Level.SEVERE, "[-x-] SOURCE " + id + ": Error getting event data.", ex);
+ received.add("[data processing error]");
+ }
+ }
+ });
+ }
+
+ final String[] postedItems = new String[MAX_ITEMS * 2];
+ try {
+ open(sources);
+
+ for (int i = 0; i < MAX_ITEMS; i++) {
+ final String item = String.format("round-1-%02d", i);
+ postItem(itemsTarget, item);
+ postedItems[i] = item;
+ sendCommand(itemsTarget, "disconnect");
+ Thread.sleep(100);
+ }
+
+ final int reconnectDelay = 1;
+ sendCommand(itemsTarget, "reconnect " + reconnectDelay);
+ sendCommand(itemsTarget, "disconnect");
+
+ Thread.sleep(reconnectDelay * 1000);
+
+ for (int i = 0; i < MAX_ITEMS; i++) {
+ final String item = String.format("round-2-%02d", i);
+ postedItems[i + MAX_ITEMS] = item;
+ postItem(itemsTarget, item);
+ }
+
+ sendCommand(itemsTarget, "reconnect now");
+
+ assertTrue("Waiting to receive all events has timed out.",
+ latch.await((1 + MAX_LISTENERS * (MAX_ITEMS + 1) * reconnectDelay) * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS));
+
+ // need to force disconnect on server in order for EventSource.close(...) to succeed with HttpUrlConnection
+ sendCommand(itemsTarget, "disconnect");
+ } finally {
+ close(sources);
+ }
+
+ final String storedItems = itemsTarget.request().get(String.class);
+ for (String item : postedItems) {
+ assertThat("Posted item '" + item + "' stored on server", storedItems, containsString(item));
+ }
+
+ int sourceId = 0;
+ for (Queue<String> queue : receivedQueues) {
+ assertThat("Received events in source " + sourceId, queue,
+ describedAs("Collection containing %0", hasItems(postedItems), Arrays.asList(postedItems).toString()));
+ assertThat("Size of received queue for source " + sourceId, queue.size(), equalTo(postedItems.length));
+ sourceId++;
+ }
+ }
+
+ private static void postItem(final WebTarget itemsTarget, final String item) {
+ final Response response = itemsTarget.request().post(Entity.form(new Form("name", item)));
+ assertEquals("Posting new item has failed.", 204, response.getStatus());
+ LOGGER.info("[-i-] POSTed item: '" + item + "'");
+ }
+
+ private static void open(final EventSource[] sources) {
+ int i = 0;
+ for (EventSource source : sources) {
+ source.open();
+ LOGGER.info("[-->] SOURCE " + i++ + " opened.");
+ }
+ }
+
+ private static void close(final EventSource[] sources) {
+ int i = 0;
+ for (EventSource source : sources) {
+ if (source.isOpen()) {
+ assertTrue("Waiting to close a source has timed out.", source.close(1, TimeUnit.SECONDS));
+// source.close(100, TimeUnit.MILLISECONDS);
+ LOGGER.info("[<--] SOURCE " + i++ + " closed.");
+ }
+ }
+ }
+
+ private static void sendCommand(final WebTarget itemsTarget, final String command) {
+ final Response response = itemsTarget.path("commands").request().post(Entity.text(command));
+ assertEquals("'" + command + "' command has failed.", 200, response.getStatus());
+ LOGGER.info("[-!-] COMMAND '" + command + "' has been processed.");
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/pom.xml b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
new file mode 100644
index 0000000..b47561b
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-request-wrappper-binding-2</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-request-wrapper-binding-2</name>
+
+ <description>Servlet integration test - Request wrapper binding 2 - ServletContainerProviderFactory, ServletContainerProvider</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-servlet-portability</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/JaxRsApplicationAutodetected.java b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/JaxRsApplicationAutodetected.java
new file mode 100644
index 0000000..fe3f465
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/JaxRsApplicationAutodetected.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Test application. This one gets registered automatically.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("autodetected")
+public class JaxRsApplicationAutodetected extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {
+ {
+ add(RequestResponseInjectedResource.class);
+ add(RequestResponseInjectedSingletonResource.class);
+ }
+ };
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedResource.java b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedResource.java
new file mode 100644
index 0000000..47370b8
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedResource.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+/**
+ * Test resource that gets injected with the actual {@link HttpServletRequest} and
+ * {@link HttpServletResponse} instance, so that we could testify custom implementations
+ * has been used there.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+public class RequestResponseInjectedResource {
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ @Context
+ HttpServletRequest request;
+
+ @Context
+ HttpServletResponse response;
+
+ @GET
+ @Path("requestType")
+ public String getRequestType() throws Exception {
+
+ // make sure we can access underlying request from another thread
+ return executor.submit(new Callable<String>() {
+ @Override
+ public String call() throws Exception {
+ return ((HttpServletRequestWrapper) request).getRequest().getClass().getName();
+ }
+ }).get();
+ }
+
+ @GET
+ @Path("responseType")
+ public String getResponseType() {
+
+ return ((HttpServletResponseWrapper) response).getResponse().getClass().getName();
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedSingletonResource.java b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedSingletonResource.java
new file mode 100644
index 0000000..f916f7e
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseInjectedSingletonResource.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2;
+
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+/**
+ * Test resource that gets injected with the actual {@link HttpServletRequest} and
+ * {@link HttpServletResponse} instance, so that we could testify custom implementations
+ * has been used there.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/singleton")
+@Singleton
+public class RequestResponseInjectedSingletonResource {
+
+ @Context
+ HttpServletRequest request;
+
+ @Context
+ HttpServletResponse response;
+
+ @GET
+ @Path("requestType")
+ public String getRequestType() {
+
+ return ((HttpServletRequestWrapper) request).getRequest().getClass().getName();
+ }
+
+ @GET
+ @Path("request/param")
+ public String getRequestAttr() {
+
+ return request.getParameter("q");
+ }
+
+ @GET
+ @Path("responseType")
+ public String getResponseType() {
+
+ return ((HttpServletResponseWrapper) response).getResponse().getClass().getName();
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java
new file mode 100644
index 0000000..db50a72
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java
@@ -0,0 +1,839 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import javax.ws.rs.core.GenericType;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+
+import org.glassfish.jersey.inject.hk2.DelayedHk2InjectionManager;
+import org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.ComponentProvider;
+import org.glassfish.jersey.server.spi.RequestScopedInitializer;
+import org.glassfish.jersey.servlet.internal.spi.NoOpServletContainerProvider;
+import org.glassfish.jersey.servlet.internal.spi.RequestContextProvider;
+import org.glassfish.jersey.servlet.internal.spi.RequestScopedInitializerProvider;
+
+import org.glassfish.hk2.api.DescriptorType;
+import org.glassfish.hk2.api.DescriptorVisibility;
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.hk2.api.ServiceHandle;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.api.TypeLiteral;
+import org.glassfish.hk2.utilities.AbstractActiveDescriptor;
+import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
+
+import org.jvnet.hk2.internal.ServiceHandleImpl;
+
+/**
+ * Servlet container provider that wraps the original Servlet request/response.
+ * The request wrapper contains a direct reference to the underlying container request
+ * in case it gets injected into a request scoped component.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class RequestResponseWrapperProvider extends NoOpServletContainerProvider {
+
+ private final Type REQUEST_TYPE = (new TypeLiteral<Ref<HttpServletRequestWrapper>>() {
+ }).getType();
+ private final Type RESPONSE_TYPE = (new TypeLiteral<Ref<HttpServletResponseWrapper>>() {
+ }).getType();
+
+ public static class DescriptorProvider implements ComponentProvider {
+
+ @Override
+ public void initialize(InjectionManager injectionManager) {
+ ServiceLocator locator = getServiceLocator(injectionManager);
+ ServiceLocatorUtilities.addOneDescriptor(locator, new HttpServletRequestDescriptor(locator));
+ }
+
+ @Override
+ public boolean bind(Class<?> component, Set<Class<?>> providerContracts) {
+ return false;
+ }
+
+ @Override
+ public void done() {
+ // nop
+ }
+ }
+
+ /**
+ * Subclass standard wrapper so that we make 100 % sure we are getting the right type.
+ * It is also final, i.e. not proxiable, which we workaround by using custom http servlet request impl.
+ */
+ public static final class RequestWrapper extends HttpServletRequestWrapper {
+
+ public RequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+ }
+
+ /**
+ * Subclass standard wrapper so that we make 100 % sure we are getting the right type.
+ * It is also final, i.e. not proxiable, which we workaround by using custom http servlet response impl.
+ */
+ public static final class ResponseWrapper extends HttpServletResponseWrapper {
+
+ public ResponseWrapper(HttpServletResponse response) {
+ super(response);
+ }
+ }
+
+ @Override
+ public boolean bindsServletRequestResponse() {
+ return true;
+ }
+
+ @Override
+ public RequestScopedInitializerProvider getRequestScopedInitializerProvider() {
+ return new RequestScopedInitializerProvider() {
+
+ @Override
+ public RequestScopedInitializer get(final RequestContextProvider context) {
+ return new RequestScopedInitializer() {
+ @Override
+ public void initialize(InjectionManager injectionManager) {
+ ServiceLocator locator = getServiceLocator(injectionManager);
+ locator.<Ref<HttpServletRequest>>getService(REQUEST_TYPE)
+ .set(finalWrap(context.getHttpServletRequest()));
+ locator.<Ref<HttpServletResponse>>getService(RESPONSE_TYPE)
+ .set(finalWrap(context.getHttpServletResponse()));
+ }
+ };
+ }
+ };
+ }
+
+ private final class Binder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+
+ bindFactory(HttpServletRequestReferencingFactory.class)
+ .to(HttpServletRequestWrapper.class).in(RequestScoped.class);
+
+ bindFactory(ReferencingFactory.<HttpServletRequestWrapper>referenceFactory())
+ .to(new GenericType<Ref<HttpServletRequestWrapper>>() {
+ }).in(RequestScoped.class);
+
+ bindFactory(HttpServletResponseFactory.class).to(HttpServletResponse.class);
+
+ bindFactory(HttpServletResponseReferencingFactory.class)
+ .to(HttpServletResponseWrapper.class).in(RequestScoped.class);
+
+ bindFactory(ReferencingFactory.<HttpServletResponseWrapper>referenceFactory())
+ .to(new GenericType<Ref<HttpServletResponseWrapper>>() {
+ }).in(RequestScoped.class);
+
+ }
+ }
+
+ private static class HttpServletRequestDescriptor extends AbstractActiveDescriptor<HttpServletRequest> {
+
+ static Set<Type> advertisedContracts = new HashSet<Type>() {
+ {
+ add(HttpServletRequest.class);
+ }
+ };
+
+ final ServiceLocator locator;
+ volatile javax.inject.Provider<Ref<HttpServletRequestWrapper>> request;
+
+ public HttpServletRequestDescriptor(final ServiceLocator locator) {
+ super(advertisedContracts,
+ PerLookup.class,
+ null, new HashSet<Annotation>(),
+ DescriptorType.CLASS, DescriptorVisibility.LOCAL,
+ 0, null, null, null, null);
+ this.locator = locator;
+ }
+
+ @Override
+ public Class<?> getImplementationClass() {
+ return HttpServletRequest.class;
+ }
+
+ @Override
+ public Type getImplementationType() {
+ return getImplementationClass();
+ }
+
+ @Override
+ public synchronized String getImplementation() {
+ return HttpServletRequest.class.getName();
+ }
+
+ @Override
+ public HttpServletRequest create(ServiceHandle<?> serviceHandle) {
+ if (request == null) {
+ request = locator.getService(new TypeLiteral<Provider<Ref<HttpServletRequestWrapper>>>() {
+ }.getType());
+ }
+
+ boolean direct = false;
+
+ if (serviceHandle instanceof ServiceHandleImpl) {
+ final ServiceHandleImpl serviceHandleImpl = (ServiceHandleImpl) serviceHandle;
+ final Class<? extends Annotation> scopeAnnotation =
+ serviceHandleImpl.getOriginalRequest().getInjecteeDescriptor().getScopeAnnotation();
+
+ if (scopeAnnotation == RequestScoped.class || scopeAnnotation == null) {
+ direct = true;
+ }
+ }
+
+
+ return !direct ? new HttpServletRequestWrapper(new MyHttpServletRequestImpl() {
+ @Override
+ HttpServletRequest getHttpServletRequest() {
+ return request.get().get();
+ }
+ }) {
+ @Override
+ public ServletRequest getRequest() {
+ return request.get().get();
+ }
+
+ }
+ : new HttpServletRequestWrapper(request.get().get());
+ }
+ }
+
+ private static class HttpServletResponseFactory implements Supplier<HttpServletResponse> {
+ private final javax.inject.Provider<Ref<HttpServletResponseWrapper>> response;
+
+ @Inject
+ public HttpServletResponseFactory(javax.inject.Provider<Ref<HttpServletResponseWrapper>> response) {
+ this.response = response;
+ }
+
+ @Override
+ @PerLookup
+ public HttpServletResponse get() {
+ return new HttpServletResponseWrapper(new HttpServletResponse() {
+
+ private HttpServletResponse getHttpServletResponse() {
+ return response.get().get();
+ }
+
+ @Override
+ public void addCookie(Cookie cookie) {
+ getHttpServletResponse().addCookie(cookie);
+ }
+
+ @Override
+ public boolean containsHeader(String s) {
+ return getHttpServletResponse().containsHeader(s);
+ }
+
+ @Override
+ public String encodeURL(String s) {
+ return getHttpServletResponse().encodeURL(s);
+ }
+
+ @Override
+ public String encodeRedirectURL(String s) {
+ return getHttpServletResponse().encodeRedirectURL(s);
+ }
+
+ @Override
+ public String encodeUrl(String s) {
+ return getHttpServletResponse().encodeUrl(s);
+ }
+
+ @Override
+ public String encodeRedirectUrl(String s) {
+ return getHttpServletResponse().encodeRedirectUrl(s);
+ }
+
+ @Override
+ public void sendError(int i, String s) throws IOException {
+ getHttpServletResponse().sendError(i, s);
+ }
+
+ @Override
+ public void sendError(int i) throws IOException {
+ getHttpServletResponse().sendError(i);
+ }
+
+ @Override
+ public void sendRedirect(String s) throws IOException {
+ getHttpServletResponse().sendRedirect(s);
+ }
+
+ @Override
+ public void setDateHeader(String s, long l) {
+ getHttpServletResponse().setDateHeader(s, l);
+ }
+
+ @Override
+ public void addDateHeader(String s, long l) {
+ getHttpServletResponse().addDateHeader(s, l);
+ }
+
+ @Override
+ public void setHeader(String h, String v) {
+ getHttpServletResponse().setHeader(h, v);
+ }
+
+ public Collection<String> getHeaderNames() {
+ return getHttpServletResponse().getHeaderNames();
+ }
+
+ public Collection<String> getHeaders(String s) {
+ return getHttpServletResponse().getHeaders(s);
+ }
+
+ public String getHeader(String s) {
+ return getHttpServletResponse().getHeader(s);
+ }
+
+ @Override
+ public void addHeader(String h, String v) {
+ getHttpServletResponse().addHeader(h, v);
+ }
+
+ @Override
+ public void setIntHeader(String s, int i) {
+ getHttpServletResponse().setIntHeader(s, i);
+ }
+
+ @Override
+ public void addIntHeader(String s, int i) {
+ getHttpServletResponse().addIntHeader(s, i);
+ }
+
+ @Override
+ public void setStatus(int i) {
+ getHttpServletResponse().setStatus(i);
+ }
+
+ @Override
+ public int getStatus() {
+ return getHttpServletResponse().getStatus();
+ }
+
+ @Override
+ public void setStatus(int i, String s) {
+ getHttpServletResponse().setStatus(i, s);
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return getHttpServletResponse().getCharacterEncoding();
+ }
+
+ @Override
+ public String getContentType() {
+ return getHttpServletResponse().getContentType();
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return getHttpServletResponse().getOutputStream();
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ return getHttpServletResponse().getWriter();
+ }
+
+ @Override
+ public void setCharacterEncoding(String s) {
+ getHttpServletResponse().setCharacterEncoding(s);
+ }
+
+ @Override
+ public void setContentLength(int i) {
+ getHttpServletResponse().setContentLength(i);
+ }
+
+ @Override
+ public void setContentType(String s) {
+ getHttpServletResponse().setContentType(s);
+ }
+
+ @Override
+ public void setBufferSize(int i) {
+ getHttpServletResponse().setBufferSize(i);
+ }
+
+ @Override
+ public int getBufferSize() {
+ return getHttpServletResponse().getBufferSize();
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ getHttpServletResponse().flushBuffer();
+ }
+
+ @Override
+ public void resetBuffer() {
+ getHttpServletResponse().resetBuffer();
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return getHttpServletResponse().isCommitted();
+ }
+
+ @Override
+ public void reset() {
+ getHttpServletResponse().reset();
+ }
+
+ @Override
+ public void setLocale(Locale locale) {
+ getHttpServletResponse().setLocale(locale);
+ }
+
+ @Override
+ public Locale getLocale() {
+ return getHttpServletResponse().getLocale();
+ }
+ }
+ ) {
+ @Override
+ public ServletResponse getResponse() {
+ return response.get().get();
+ }
+ };
+ }
+
+ }
+
+ @SuppressWarnings("JavaDoc")
+ private static class HttpServletRequestReferencingFactory extends ReferencingFactory<HttpServletRequestWrapper> {
+
+ @Inject
+ public HttpServletRequestReferencingFactory(
+ final javax.inject.Provider<Ref<HttpServletRequestWrapper>> referenceFactory) {
+
+ super(referenceFactory);
+ }
+ }
+
+ @SuppressWarnings("JavaDoc")
+ private static class HttpServletResponseReferencingFactory extends ReferencingFactory<HttpServletResponseWrapper> {
+
+ @Inject
+ public HttpServletResponseReferencingFactory(
+ final javax.inject.Provider<Ref<HttpServletResponseWrapper>> referenceFactory) {
+
+ super(referenceFactory);
+ }
+
+ }
+
+ @Override
+ public void configure(final ResourceConfig resourceConfig) throws ServletException {
+ resourceConfig.register(new Binder());
+ }
+
+ private HttpServletRequest finalWrap(final HttpServletRequest request) {
+ return new RequestWrapper(request);
+ }
+
+ private HttpServletResponse finalWrap(final HttpServletResponse response) {
+ return new ResponseWrapper(response);
+ }
+
+ private abstract static class MyHttpServletRequestImpl implements HttpServletRequest {
+
+ @Override
+ public String getAuthType() {
+ return getHttpServletRequest().getAuthType();
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+ return getHttpServletRequest().authenticate(response);
+ }
+
+ @Override
+ public boolean isAsyncSupported() {
+ return getHttpServletRequest().isAsyncSupported();
+ }
+
+ @Override
+ public boolean isAsyncStarted() {
+ return getHttpServletRequest().isAsyncStarted();
+ }
+
+ @Override
+ public AsyncContext startAsync() throws IllegalStateException {
+ return getHttpServletRequest().startAsync();
+ }
+
+ @Override
+ public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws IllegalStateException {
+ return getHttpServletRequest().startAsync(request, response);
+ }
+
+ abstract HttpServletRequest getHttpServletRequest();
+
+ @Override
+ public Cookie[] getCookies() {
+ return getHttpServletRequest().getCookies();
+ }
+
+ @Override
+ public long getDateHeader(String s) {
+ return getHttpServletRequest().getDateHeader(s);
+ }
+
+ @Override
+ public Part getPart(String s) throws ServletException, IOException {
+ return getHttpServletRequest().getPart(s);
+ }
+
+ @Override
+ public Collection<Part> getParts() throws ServletException, IOException {
+ return getHttpServletRequest().getParts();
+ }
+
+ @Override
+ public String getHeader(String s) {
+ return getHttpServletRequest().getHeader(s);
+ }
+
+ @Override
+ public Enumeration getHeaders(String s) {
+ return getHttpServletRequest().getHeaders(s);
+ }
+
+ @Override
+ public Enumeration getHeaderNames() {
+ return getHttpServletRequest().getHeaderNames();
+ }
+
+ @Override
+ public int getIntHeader(String s) {
+ return getHttpServletRequest().getIntHeader(s);
+ }
+
+ @Override
+ public String getMethod() {
+ return getHttpServletRequest().getMethod();
+ }
+
+ @Override
+ public String getPathInfo() {
+ return getHttpServletRequest().getPathInfo();
+ }
+
+ @Override
+ public String getPathTranslated() {
+ return getHttpServletRequest().getPathTranslated();
+ }
+
+ @Override
+ public String getContextPath() {
+ return getHttpServletRequest().getContextPath();
+ }
+
+ @Override
+ public String getQueryString() {
+ return getHttpServletRequest().getQueryString();
+ }
+
+ @Override
+ public String getRemoteUser() {
+ return getHttpServletRequest().getRemoteUser();
+ }
+
+ @Override
+ public boolean isUserInRole(String s) {
+ return getHttpServletRequest().isUserInRole(s);
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return getHttpServletRequest().getUserPrincipal();
+ }
+
+ @Override
+ public String getRequestedSessionId() {
+ return getHttpServletRequest().getRequestedSessionId();
+ }
+
+ @Override
+ public String getRequestURI() {
+ return getHttpServletRequest().getRequestURI();
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ return getHttpServletRequest().getRequestURL();
+ }
+
+ @Override
+ public String getServletPath() {
+ return getHttpServletRequest().getServletPath();
+ }
+
+ @Override
+ public HttpSession getSession(boolean b) {
+ return getHttpServletRequest().getSession(b);
+ }
+
+ @Override
+ public HttpSession getSession() {
+ return getHttpServletRequest().getSession();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid() {
+ return getHttpServletRequest().isRequestedSessionIdValid();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie() {
+ return getHttpServletRequest().isRequestedSessionIdFromCookie();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL() {
+ return getHttpServletRequest().isRequestedSessionIdFromURL();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromUrl() {
+ return getHttpServletRequest().isRequestedSessionIdFromUrl();
+ }
+
+ @Override
+ public Object getAttribute(String s) {
+ return getHttpServletRequest().getAttribute(s);
+ }
+
+ @Override
+ public Enumeration getAttributeNames() {
+ return getHttpServletRequest().getAttributeNames();
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return getHttpServletRequest().getCharacterEncoding();
+ }
+
+ @Override
+ public void setCharacterEncoding(String s) throws UnsupportedEncodingException {
+ getHttpServletRequest().setCharacterEncoding(s);
+ }
+
+ @Override
+ public int getContentLength() {
+ return getHttpServletRequest().getContentLength();
+ }
+
+ @Override
+ public String getContentType() {
+ return getHttpServletRequest().getContentType();
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ return getHttpServletRequest().getInputStream();
+ }
+
+ @Override
+ public String getParameter(String s) {
+ return getHttpServletRequest().getParameter(s);
+ }
+
+ @Override
+ public Enumeration getParameterNames() {
+ return getHttpServletRequest().getParameterNames();
+ }
+
+ @Override
+ public String[] getParameterValues(String s) {
+ return getHttpServletRequest().getParameterValues(s);
+ }
+
+ @Override
+ public Map getParameterMap() {
+ return getHttpServletRequest().getParameterMap();
+ }
+
+ @Override
+ public String getProtocol() {
+ return getHttpServletRequest().getProtocol();
+ }
+
+ @Override
+ public String getScheme() {
+ return getHttpServletRequest().getScheme();
+ }
+
+ @Override
+ public String getServerName() {
+ return getHttpServletRequest().getServerName();
+ }
+
+ @Override
+ public int getServerPort() {
+ return getHttpServletRequest().getServerPort();
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return getHttpServletRequest().getReader();
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ return getHttpServletRequest().getRemoteAddr();
+ }
+
+ @Override
+ public String getRemoteHost() {
+ return getHttpServletRequest().getRemoteHost();
+ }
+
+ @Override
+ public void setAttribute(String s, Object o) {
+ getHttpServletRequest().setAttribute(s, o);
+ }
+
+ @Override
+ public void removeAttribute(String s) {
+ getHttpServletRequest().removeAttribute(s);
+ }
+
+ @Override
+ public Locale getLocale() {
+ return getHttpServletRequest().getLocale();
+ }
+
+ @Override
+ public Enumeration getLocales() {
+ return getHttpServletRequest().getLocales();
+ }
+
+ @Override
+ public boolean isSecure() {
+ return getHttpServletRequest().isSecure();
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String s) {
+ return getHttpServletRequest().getRequestDispatcher(s);
+ }
+
+ @Override
+ public String getRealPath(String s) {
+ return getHttpServletRequest().getRealPath(s);
+ }
+
+ @Override
+ public int getRemotePort() {
+ return getHttpServletRequest().getRemotePort();
+ }
+
+ @Override
+ public String getLocalName() {
+ return getHttpServletRequest().getLocalName();
+ }
+
+ @Override
+ public String getLocalAddr() {
+ return getHttpServletRequest().getLocalAddr();
+ }
+
+ @Override
+ public int getLocalPort() {
+ return getHttpServletRequest().getLocalPort();
+ }
+
+ @Override
+ public DispatcherType getDispatcherType() {
+ return getHttpServletRequest().getDispatcherType();
+ }
+
+ @Override
+ public AsyncContext getAsyncContext() {
+ return getHttpServletRequest().getAsyncContext();
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return getHttpServletRequest().getServletContext();
+ }
+
+ @Override
+ public void logout() throws ServletException {
+ getHttpServletRequest().logout();
+ }
+
+ @Override
+ public void login(String u, String p) throws ServletException {
+ getHttpServletRequest().login(u, p);
+ }
+ }
+
+ private static ServiceLocator getServiceLocator(InjectionManager injectionManager) {
+ if (injectionManager instanceof ImmediateHk2InjectionManager) {
+ return ((ImmediateHk2InjectionManager) injectionManager).getServiceLocator();
+ } else if (injectionManager instanceof DelayedHk2InjectionManager) {
+ return ((DelayedHk2InjectionManager) injectionManager).getServiceLocator();
+ } else {
+ throw new RuntimeException("Invalid InjectionManager");
+ }
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider b/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
new file mode 100644
index 0000000..e6780ff
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseWrapperProvider$DescriptorProvider
\ No newline at end of file
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider b/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
new file mode 100644
index 0000000..543851e
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseWrapperProvider
\ No newline at end of file
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-request-wrapper-binding-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..aab05c4
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+
+ <servlet>
+ <servlet-name>jerseyApp</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseInjectedResource,
+ org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseInjectedSingletonResource
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jerseyApp</servlet-name>
+ <url-pattern>/webxmlconfigured/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AbstractRequestResponseTypeTest.java b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AbstractRequestResponseTypeTest.java
new file mode 100644
index 0000000..5631450
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AbstractRequestResponseTypeTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper2;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseWrapperProvider;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Make sure that injected request/response instances
+ * are of the types injected by {@link RequestResponseWrapperProvider}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public abstract class AbstractRequestResponseTypeTest extends JerseyTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testRequestType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("requestType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.RequestWrapper.class.getName())));
+ }
+
+ @Test
+ public void testResponseType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("responseType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.ResponseWrapper.class.getName())));
+ }
+
+ @Test
+ public void testSingletonRequestType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("singleton/requestType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.RequestWrapper.class.getName())));
+ }
+
+ @Test
+ public void testSingletonRequestAttr() throws Exception {
+ for (String q : new String[] {"1", "2", "3", "95", "98", "NT", "2000", "XP", "Vista", "7", "8", "10"}) {
+ _testSingletonRequestAttr("one");
+ }
+ }
+
+ public void _testSingletonRequestAttr(String q) throws Exception {
+ final String requestType = target(getAppBasePath()).path("singleton/request/param")
+ .queryParam("q", q).request().get(String.class);
+ assertThat(requestType, is(equalTo(q)));
+ }
+
+ @Test
+ public void testSingletonResponseType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("singleton/responseType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.ResponseWrapper.class.getName())));
+ }
+
+ protected abstract String getAppBasePath();
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AutodetectedAppRequestResponseTypeITCase.java b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AutodetectedAppRequestResponseTypeITCase.java
new file mode 100644
index 0000000..13a6063
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/AutodetectedAppRequestResponseTypeITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper2;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.JaxRsApplicationAutodetected;
+
+/**
+ * Test for the autodetected JAX-RS app.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class AutodetectedAppRequestResponseTypeITCase extends AbstractRequestResponseTypeTest {
+
+ @Override
+ protected String getAppBasePath() {
+ return "autodetected";
+ }
+
+ @Override
+ protected Application configure() {
+ return ResourceConfig.forApplicationClass(JaxRsApplicationAutodetected.class);
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/WebXmlConfiguredAppRequestResponseTypeITCase.java b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/WebXmlConfiguredAppRequestResponseTypeITCase.java
new file mode 100644
index 0000000..9a028dc
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper2/WebXmlConfiguredAppRequestResponseTypeITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper2;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding2.RequestResponseInjectedResource;
+
+/**
+ * Test for the web.xml configured JAX-RS app.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class WebXmlConfiguredAppRequestResponseTypeITCase extends AbstractRequestResponseTypeTest {
+
+ @Override
+ protected String getAppBasePath() {
+ return "webxmlconfigured";
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RequestResponseInjectedResource.class);
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/pom.xml b/tests/integration/servlet-request-wrapper-binding/pom.xml
new file mode 100644
index 0000000..8e869c4
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-request-wrappper-binding</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-request-wrapper-binding</name>
+
+ <description>Servlet integration test - Request wrapper binding - ServletContainerProviderFactory, ServletContainerProvider</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-servlet-portability</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/JaxRsApplicationAutodetected.java b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/JaxRsApplicationAutodetected.java
new file mode 100644
index 0000000..1fe4126
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/JaxRsApplicationAutodetected.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Test application. This one gets registered automatically.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@ApplicationPath("autodetected")
+public class JaxRsApplicationAutodetected extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<Class<?>>() {
+ {
+ add(RequestResponseInjectedResource.class);
+ }
+ };
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseInjectedResource.java b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseInjectedResource.java
new file mode 100644
index 0000000..54cc690
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseInjectedResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+
+/**
+ * Test resource that gets injected with the actual {@link HttpServletRequest} and
+ * {@link HttpServletResponse} instance, so that we could testify custom implementations
+ * has been used there.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+public class RequestResponseInjectedResource {
+
+ @Context
+ HttpServletRequest request;
+
+ @Context
+ HttpServletResponse response;
+
+ @GET
+ @Path("requestType")
+ public String getRequestType() {
+
+ return request.getClass().getName();
+ }
+
+ @GET
+ @Path("responseType")
+ public String getResponseType() {
+
+ return response.getClass().getName();
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseWrapperProvider.java b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseWrapperProvider.java
new file mode 100644
index 0000000..09f40a7
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding/RequestResponseWrapperProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.server.spi.RequestScopedInitializer;
+import org.glassfish.jersey.servlet.internal.spi.NoOpServletContainerProvider;
+import org.glassfish.jersey.servlet.internal.spi.RequestScopedInitializerProvider;
+
+/**
+ * Servlet container provider that wraps the original Servlet request/response.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class RequestResponseWrapperProvider extends NoOpServletContainerProvider {
+
+ /**
+ * Subclass standard wrapper so that we make 100 % sure we are getting the right type.
+ */
+ public static class RequestWrapper extends HttpServletRequestWrapper {
+
+ public RequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+ }
+
+ /**
+ * Subclass standard wrapper so that we make 100 % sure we are getting the right type.
+ */
+ public static class ResponseWrapper extends HttpServletResponseWrapper {
+
+ public ResponseWrapper(HttpServletResponse response) {
+ super(response);
+ }
+ }
+
+ @Override
+ public RequestScopedInitializerProvider getRequestScopedInitializerProvider() {
+ return context -> (RequestScopedInitializer) injectionManager -> {
+ injectionManager.<Ref<HttpServletRequest>>getInstance(HTTP_SERVLET_REQUEST_TYPE)
+ .set(wrapped(context.getHttpServletRequest()));
+ injectionManager.<Ref<HttpServletResponse>>getInstance(HTTP_SERVLET_RESPONSE_TYPE)
+ .set(wrapped(context.getHttpServletResponse()));
+ };
+ }
+
+ private HttpServletRequest wrapped(final HttpServletRequest request) {
+ return new RequestWrapper(request);
+ }
+
+ private HttpServletResponse wrapped(final HttpServletResponse response) {
+ return new ResponseWrapper(response);
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider b/tests/integration/servlet-request-wrapper-binding/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
new file mode 100644
index 0000000..fd57f7c
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/main/resources/META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding.RequestResponseWrapperProvider
\ No newline at end of file
diff --git a/tests/integration/servlet-request-wrapper-binding/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-request-wrapper-binding/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..0cee595
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+
+ <servlet>
+ <servlet-name>jerseyApp</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding.RequestResponseInjectedResource</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jerseyApp</servlet-name>
+ <url-pattern>/webxmlconfigured/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AbstractRequestResponseTypeTest.java b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AbstractRequestResponseTypeTest.java
new file mode 100644
index 0000000..4f4710d
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AbstractRequestResponseTypeTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding.RequestResponseWrapperProvider;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.equalTo;
+
+import org.junit.Test;
+
+/**
+ * Make sure that injected request/response instances
+ * are of the types injected by {@link RequestResponseWrapperProvider}.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public abstract class AbstractRequestResponseTypeTest extends JerseyTest {
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testRequestType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("requestType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.RequestWrapper.class.getName())));
+ }
+
+ @Test
+ public void testResponseType() throws Exception {
+ final String requestType = target(getAppBasePath()).path("responseType").request().get(String.class);
+ assertThat(requestType, is(equalTo(RequestResponseWrapperProvider.ResponseWrapper.class.getName())));
+ }
+
+ protected abstract String getAppBasePath();
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AutodetectedAppRequestResponseTypeITCase.java b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AutodetectedAppRequestResponseTypeITCase.java
new file mode 100644
index 0000000..7b7403a
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/AutodetectedAppRequestResponseTypeITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding.JaxRsApplicationAutodetected;
+
+/**
+ * Test for the autodetected JAX-RS app.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class AutodetectedAppRequestResponseTypeITCase extends AbstractRequestResponseTypeTest {
+
+ @Override
+ protected String getAppBasePath() {
+ return "autodetected";
+ }
+
+ @Override
+ protected Application configure() {
+ return ResourceConfig.forApplicationClass(JaxRsApplicationAutodetected.class);
+ }
+}
diff --git a/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/WebXmlConfiguredAppRequestResponseTypeITCase.java b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/WebXmlConfiguredAppRequestResponseTypeITCase.java
new file mode 100644
index 0000000..f6a85ad
--- /dev/null
+++ b/tests/integration/servlet-request-wrapper-binding/src/test/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper/WebXmlConfiguredAppRequestResponseTypeITCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlet_request_wrapper;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.integration.servlet_request_wrapper_binding.RequestResponseInjectedResource;
+
+/**
+ * Test for the web.xml configured JAX-RS app.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class WebXmlConfiguredAppRequestResponseTypeITCase extends AbstractRequestResponseTypeTest {
+
+ @Override
+ protected String getAppBasePath() {
+ return "webxmlconfigured";
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RequestResponseInjectedResource.class);
+ }
+}
diff --git a/tests/integration/servlet-tests/pom.xml b/tests/integration/servlet-tests/pom.xml
new file mode 100644
index 0000000..015852d
--- /dev/null
+++ b/tests/integration/servlet-tests/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>servlet-tests</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-servlet-tests</name>
+
+ <description>Set of smaller unrelated servlet-specific tests.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404Resource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404Resource.java
new file mode 100644
index 0000000..4fca464
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404Resource.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author Martin Matula
+ */
+@Path("404")
+public class CacheControlOn404Resource {
+ @GET
+ public Response get404() {
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(10);
+ return Response.status(Response.Status.NOT_FOUND).cacheControl(cc).type("text/plain").entity("404 Not Found").build();
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CustomMediaTypeAnd404Resource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CustomMediaTypeAnd404Resource.java
new file mode 100644
index 0000000..08d2952
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/CustomMediaTypeAnd404Resource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Miroslav Fuksa
+ */
+@Path("resource404")
+public class CustomMediaTypeAnd404Resource {
+ @Path("content-type-entity")
+ @GET
+ public Response getSpecialContentType() {
+ return Response.status(Response.Status.NOT_FOUND).type("application/something").entity("not found custom entity").build();
+ }
+
+ @Path("content-type-empty-entity")
+ @GET
+ public Response getSpecialContentTypeWithEmptyEntityString() {
+ return Response.status(Response.Status.NOT_FOUND).type("application/something").entity("").build();
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathResource.java
new file mode 100644
index 0000000..11b5c2a
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathResource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Martin Matula
+ */
+@Path("contextPathResource")
+public class FilterContextPathResource {
+ @GET
+ public String get() {
+ return "contextPathResource";
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterForwardOn404Resource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterForwardOn404Resource.java
new file mode 100644
index 0000000..316b007
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterForwardOn404Resource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Martin Matula
+ */
+@Path("forwardingFilter/resource")
+public class FilterForwardOn404Resource {
+ @GET
+ public String get() {
+ return "forwardingFilter/resource";
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterNoContextPathResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterNoContextPathResource.java
new file mode 100644
index 0000000..739a2d0
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterNoContextPathResource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Martin Matula
+ */
+@Path("filter/resource")
+public class FilterNoContextPathResource {
+ @GET
+ public String get() {
+ return "filter/resource";
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterStaticContentResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterStaticContentResource.java
new file mode 100644
index 0000000..256ab41
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FilterStaticContentResource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Martin Matula
+ */
+@Path("staticContentFilter/resource")
+public class FilterStaticContentResource {
+ @GET
+ public String get() {
+ return "staticContentFilter/resource";
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionFilter.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionFilter.java
new file mode 100644
index 0000000..bda0d3a
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionFilter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * @author Martin Matula
+ */
+public class FormConsumptionFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ // consume entity
+ servletRequest.getParameter("text");
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionResource.java
new file mode 100644
index 0000000..f0910fd
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionResource.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Martin Matula
+ */
+@Path("form-consumption")
+public class FormConsumptionResource {
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public String postIt(@FormParam("text") String text) {
+ return text;
+ }
+
+
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Path("encoding")
+ public String postEncoding(@Encoded @FormParam("text") String text) throws UnsupportedEncodingException {
+ return URLDecoder.decode(text, "UTF-8");
+ }
+
+ @PUT
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public String putIt(@FormParam("text") String text) {
+ return text;
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SecuredResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SecuredResource.java
new file mode 100644
index 0000000..6137675
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SecuredResource.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.annotation.security.RolesAllowed;
+
+/**
+ * @author Petr Bouda
+ */
+@Path("admin")
+public class SecuredResource {
+
+ @GET
+ @RolesAllowed("admin")
+ public String secured() {
+ return "Secured";
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SuppressContentLengthFilter.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SuppressContentLengthFilter.java
new file mode 100644
index 0000000..abb2ac6
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/SuppressContentLengthFilter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */package org.glassfish.jersey.tests.integration.servlettests;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+/**
+ * JERSEY-2936 reproducer filter.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class SuppressContentLengthFilter implements Filter {
+
+ public static final String PARAMETER_NAME_SUPPRESS_CONTENT_LENGTH = "SuppressContentLength";
+
+ public void doFilter(final ServletRequest request, ServletResponse response, final FilterChain chain)
+ throws IOException, ServletException {
+ if (Boolean.parseBoolean(request.getParameter(PARAMETER_NAME_SUPPRESS_CONTENT_LENGTH))) {
+ response = new HttpServletResponseWrapper((HttpServletResponse) response) {
+ @Override
+ public void setContentLength(int len) {
+ // do not delegate to original ServletResponse -> response is NOT committed
+ }
+ };
+ }
+ chain.doFilter(request, response);
+ }
+
+ public void init(FilterConfig filterConfig) {
+ //NOOP
+ }
+
+ public void destroy() {
+ //NOOP
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5d9d99e
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <!-- servlet for generic use (has all resources) -->
+ <servlet>
+ <servlet-name>testServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>testServlet</servlet-name>
+ <url-pattern>/servlet/*</url-pattern>
+ </servlet-mapping>
+
+ <!-- filter to test NOT commited responses -->
+ <filter>
+ <filter-name>SuppressContentLengthFilter</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.servlettests.SuppressContentLengthFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>SuppressContentLengthFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- filter for generic use (has all resources) -->
+ <filter>
+ <filter-name>testFilter</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testFilter</filter-name>
+ <url-pattern>/filter/*</url-pattern>
+ </filter-mapping>
+
+ <!-- filter context path -->
+ <filter>
+ <filter-name>testFilter2</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.FilterContextPathResource
+ org.glassfish.jersey.tests.integration.servlettests.FilterNoContextPathResource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.filter.contextPath</param-name>
+ <param-value>/contextPathFilter/</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testFilter2</filter-name>
+ <url-pattern>/contextPathFilter/*</url-pattern>
+ </filter-mapping>
+
+ <!-- forward on 404 -->
+ <filter>
+ <filter-name>testFilter3</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.FilterForwardOn404Resource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.filter.forwardOn404</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testFilter3</filter-name>
+ <url-pattern>/forwardingFilter/*</url-pattern>
+ </filter-mapping>
+
+ <!-- static content regex -->
+ <filter>
+ <filter-name>testFilter4</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.FilterStaticContentResource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.filter.staticContentRegex</param-name>
+ <param-value>/staticContentFilter/.*\.jsp</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>testFilter4</filter-name>
+ <url-pattern>/staticContentFilter/*</url-pattern>
+ </filter-mapping>
+
+ <!-- form consumption -->
+ <filter>
+ <filter-name>FormConsumptionFilter</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.servlettests.FormConsumptionFilter</filter-class>
+ </filter>
+ <servlet>
+ <servlet-name>FormConsumptionServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.FormConsumptionResource</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>FormConsumptionServlet</servlet-name>
+ <url-pattern>/form-consumption/*</url-pattern>
+ </servlet-mapping>
+ <filter-mapping>
+ <filter-name>FormConsumptionFilter</filter-name>
+ <url-pattern>/form-consumption/*</url-pattern>
+ </filter-mapping>
+
+ <!-- 404 -->
+ <filter>
+ <filter-name>custom404</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.CustomMediaTypeAnd404Resource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.servlet.filter.contextPath</param-name>
+ <param-value>/custom404/</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>custom404</filter-name>
+ <url-pattern>/custom404/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/integration/servlet-tests/src/main/webapp/filter/index.jsp b/tests/integration/servlet-tests/src/main/webapp/filter/index.jsp
new file mode 100644
index 0000000..6017d94
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/webapp/filter/index.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+<head>
+ <title></title>
+</head>
+<body>
+
+</body>
+</html>
diff --git a/tests/integration/servlet-tests/src/main/webapp/forwardingFilter/index.jsp b/tests/integration/servlet-tests/src/main/webapp/forwardingFilter/index.jsp
new file mode 100644
index 0000000..6017d94
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/webapp/forwardingFilter/index.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+<head>
+ <title></title>
+</head>
+<body>
+
+</body>
+</html>
diff --git a/tests/integration/servlet-tests/src/main/webapp/staticContentFilter/index.jsp b/tests/integration/servlet-tests/src/main/webapp/staticContentFilter/index.jsp
new file mode 100644
index 0000000..6017d94
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/webapp/staticContentFilter/index.jsp
@@ -0,0 +1,27 @@
+<%--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+<head>
+ <title></title>
+</head>
+<body>
+
+</body>
+</html>
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404ITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404ITCase.java
new file mode 100644
index 0000000..5697e39
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/CacheControlOn404ITCase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class related to issue JERSEY-1189.
+ * Confirms that if one sends an entity with the error status, the cache control
+ * headers don't get reset by the container.
+ *
+ * @author Martin Matula
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class CacheControlOn404ITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(CacheControlOn404Resource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void test404() throws Exception {
+ test404Impl(false);
+ }
+
+ @Test
+ public void test404SuppressContentLength() throws Exception {
+ test404Impl(true);
+ }
+
+ private void test404Impl(final boolean suppressContentLength) {
+ Response r = target("servlet").path("404")
+ .queryParam(SuppressContentLengthFilter.PARAMETER_NAME_SUPPRESS_CONTENT_LENGTH, suppressContentLength)
+ .request().get();
+ assertEquals(404, r.getStatus());
+ assertEquals("404 Not Found", r.readEntity(String.class));
+ final String[] values = r.getHeaderString(HttpHeaders.CACHE_CONTROL).split(",");
+ assertEquals(2, values.length);
+ assertEquals("no-transform", values[0].trim());
+ assertEquals("max-age=10", values[1].trim());
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/Custom404MediaTypeITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/Custom404MediaTypeITCase.java
new file mode 100644
index 0000000..619d5ba
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/Custom404MediaTypeITCase.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Miroslav Fuksa
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Custom404MediaTypeITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testCustom404() {
+ testCustom404Impl(false);
+ }
+
+ @Test
+ public void testCustom404WithEmtpyEntityString() {
+ testCustom404WithEmtpyEntityStringImpl(false);
+ }
+
+ @Test
+ public void testCustom404SuppressContentLength() {
+ testCustom404Impl(true);
+ }
+
+ @Test
+ public void testCustom404WithEmtpyEntityStringSuppressContentLength() {
+ testCustom404WithEmtpyEntityStringImpl(true);
+ }
+
+ private void testCustom404Impl(final boolean suppressContentLength) {
+ final Response response = target().path("custom404/resource404/content-type-entity")
+ .queryParam(SuppressContentLengthFilter.PARAMETER_NAME_SUPPRESS_CONTENT_LENGTH, suppressContentLength)
+ .request()
+ .get();
+ Assert.assertEquals(404, response.getStatus());
+ Assert.assertEquals("application/something", response.getMediaType().toString());
+ Assert.assertEquals("not found custom entity", response.readEntity(String.class));
+ }
+
+ private void testCustom404WithEmtpyEntityStringImpl(final boolean suppressContentLength) {
+ final Response response = target().path("custom404/resource404/content-type-empty-entity")
+ .queryParam(SuppressContentLengthFilter.PARAMETER_NAME_SUPPRESS_CONTENT_LENGTH, suppressContentLength)
+ .request().get();
+ Assert.assertEquals(404, response.getStatus());
+ Assert.assertEquals("application/something", response.getMediaType().toString());
+ Assert.assertEquals("", response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/DuplicateHeaderITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/DuplicateHeaderITCase.java
new file mode 100644
index 0000000..2856ecb
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/DuplicateHeaderITCase.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class DuplicateHeaderITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testDuplicateHeader() throws IOException {
+ testDuplicateHeaderImpl("contextPathFilter/contextPathResource");
+ testDuplicateHeaderImpl("servlet/contextPathResource");
+ }
+
+ private void testDuplicateHeaderImpl(final String path) throws IOException {
+ testDuplicateHeaderImpl(0, HttpURLConnection.HTTP_OK, path);
+ testDuplicateHeaderImpl(1, HttpURLConnection.HTTP_OK, path);
+ testDuplicateHeaderImpl(2, HttpURLConnection.HTTP_BAD_REQUEST, path);
+ }
+
+ private void testDuplicateHeaderImpl(final int headerCount, int expectedResponseCode, final String path)
+ throws IOException {
+ final String headerName = HttpHeaders.CONTENT_TYPE;
+ URL getUrl = UriBuilder.fromUri(getBaseUri()).path(path).build().toURL();
+ HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
+ try {
+ connection.setRequestMethod("GET");
+ for (int i = 0; i < headerCount; i++) {
+ connection.addRequestProperty(headerName, "N/A");
+ }
+ connection.connect();
+ assertEquals(path + " [" + headerName + ":" + headerCount + "x]", expectedResponseCode, connection.getResponseCode());
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathITCase.java
new file mode 100644
index 0000000..60e99d3
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FilterContextPathITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class FilterContextPathITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testContextPathResource() {
+ assertEquals("contextPathResource", target("contextPathFilter/contextPathResource").request().get(String.class));
+ }
+
+ @Test
+ public void testNoContextPathResource() {
+ assertEquals("filter/resource", target("filter/resource").request().get(String.class));
+ }
+
+ @Test
+ public void testOtherResourceUnreachable() {
+ Response r = target("filter/contextPathResource").request().get();
+ assertEquals(404, r.getStatus());
+ }
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionITCase.java
new file mode 100644
index 0000000..af7a5f9
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/FormConsumptionITCase.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class FormConsumptionITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testPut() {
+ Form form = new Form();
+ form.param("text", "this is a test");
+ String result = target("form-consumption/form-consumption").request().put(Entity.form(form), String.class);
+ assertEquals(form.asMap().getFirst("text"), result);
+ }
+
+ @Test
+ public void testPost() {
+ Form form = new Form();
+ form.param("text", "this is a test");
+ String result = target("form-consumption/form-consumption").request().post(Entity.form(form), String.class);
+ assertEquals(form.asMap().getFirst("text"), result);
+ }
+
+ @Test
+ public void testPostWithEncoding() {
+ Form form = new Form();
+ form.param("text", "this is an encoding test +-*/=");
+ String result = target("form-consumption/form-consumption/encoding").request().post(Entity.form(form), String.class);
+ assertEquals(form.asMap().getFirst("text"), result);
+ }
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/ForwardOn404ITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/ForwardOn404ITCase.java
new file mode 100644
index 0000000..1bc99e9
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/ForwardOn404ITCase.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class ForwardOn404ITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testResourceReachable() {
+ assertEquals("forwardingFilter/resource", target("forwardingFilter/resource").request().get(String.class));
+ }
+
+ @Test
+ public void testIndexReachable() {
+ Response r = target("forwardingFilter/index.jsp").request().get();
+ assertEquals(200, r.getStatus());
+ }
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/InvalidRequestUriITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/InvalidRequestUriITCase.java
new file mode 100644
index 0000000..db67e95
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/InvalidRequestUriITCase.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class related to issue JERSEY-2680.
+ *
+ * @author Michal Gajdos
+ */
+public class InvalidRequestUriITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testInvalidRequestUriFilter() throws Exception {
+ invalidRequestUri("filter");
+ }
+
+ @Test
+ public void testInvalidRequestUriServlet() throws Exception {
+ invalidRequestUri("servlet");
+ }
+
+ public void invalidRequestUri(final String path) throws Exception {
+ final URL url = new URL(getBaseUri().toString() + path + "/resource{");
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Accept", "text/plain");
+ connection.connect();
+
+ assertEquals(400, connection.getResponseCode());
+ }
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/RolesAllowedFilterITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/RolesAllowedFilterITCase.java
new file mode 100644
index 0000000..a22f0c8
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/RolesAllowedFilterITCase.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Petr Bouda
+ */
+public class RolesAllowedFilterITCase extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ // Dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void test403() throws Exception {
+ Response r = target("servlet/admin").request().get();
+ assertEquals(403, r.getStatus());
+ }
+}
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/StaticContentRegexITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/StaticContentRegexITCase.java
new file mode 100644
index 0000000..70647e2
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/StaticContentRegexITCase.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Martin Matula
+ */
+public class StaticContentRegexITCase extends JerseyTest {
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testIndexUnreachable() {
+ Response r = target("filter").path("index.jsp").request().get();
+ assertEquals(404, r.getStatus());
+ }
+
+ @Test
+ public void testIndexReachable() {
+ Response r = target("staticContentFilter/index.jsp").request().get();
+ assertEquals(200, r.getStatus());
+ }
+
+ @Test
+ public void testResourceReachable() {
+ Response r = target("staticContentFilter/resource").request().get();
+ assertEquals(200, r.getStatus());
+ assertEquals("staticContentFilter/resource", r.readEntity(String.class));
+ }
+}
diff --git a/tests/integration/sonar-test/pom.xml b/tests/integration/sonar-test/pom.xml
new file mode 100644
index 0000000..b897be8
--- /dev/null
+++ b/tests/integration/sonar-test/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sonar-test</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-sonar-test</name>
+
+ <description>
+ The purpose of this module is to provide an ability to check whether Sonar's code coverage includes
+ lines of code executed from an externally executed JVM, Jetty web server in this case.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestApplication.java b/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestApplication.java
new file mode 100644
index 0000000..d5b67e7
--- /dev/null
+++ b/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestApplication.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.sonar;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * Jersey application for code coverage testing.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@ApplicationPath("/")
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(TestResource.class);
+ }
+}
diff --git a/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestResource.java b/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestResource.java
new file mode 100644
index 0000000..b8bfaab
--- /dev/null
+++ b/tests/integration/sonar-test/src/main/java/org/glassfish/jersey/tests/integration/sonar/TestResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.sonar;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.glassfish.jersey.internal.sonar.SonarJerseyCommon;
+import org.glassfish.jersey.server.internal.sonar.SonarJerseyServer;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/")
+@Produces("text/plain")
+public class TestResource {
+
+ @GET
+ @Path("test")
+ public String helloServer() {
+ return new SonarJerseyCommon().integrationServerJvm() + " " + new SonarJerseyServer().integrationServerJvm();
+ }
+
+}
diff --git a/tests/integration/sonar-test/src/main/webapp/WEB-INF/web.xml b/tests/integration/sonar-test/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ab6014a
--- /dev/null
+++ b/tests/integration/sonar-test/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>jersey</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.sonar.TestApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>jersey</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/integration/sonar-test/src/test/java/org/glassfish/jersey/tests/integration/sonar/JerseySonarITCase.java b/tests/integration/sonar-test/src/test/java/org/glassfish/jersey/tests/integration/sonar/JerseySonarITCase.java
new file mode 100644
index 0000000..1c9f078
--- /dev/null
+++ b/tests/integration/sonar-test/src/test/java/org/glassfish/jersey/tests/integration/sonar/JerseySonarITCase.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.sonar;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.internal.sonar.SonarJerseyCommon;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.internal.sonar.SonarJerseyServer;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class JerseySonarITCase extends JerseyTest {
+
+ @Test
+ public void testIntegrationServerJvm() {
+ final String string = target("test").request().get(String.class);
+
+ Assert.assertEquals("common server jvm server server jvm", string);
+ }
+
+ @Test
+ public void testIntegrationTestJvm() {
+ final String string = new SonarJerseyCommon().integrationTestJvm() + " " + new SonarJerseyServer().integrationTestJvm();
+
+ Assert.assertEquals("common test jvm server test jvm", string);
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(TestApplication.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+}
diff --git a/tests/integration/spring4/README.txt b/tests/integration/spring4/README.txt
new file mode 100644
index 0000000..9a105f7
--- /dev/null
+++ b/tests/integration/spring4/README.txt
@@ -0,0 +1,30 @@
+
+tests
+=====
+
+Tests are located in jersey-spring-test module.
+The module contains a test webapp and test code.
+The tests can be run in Jersey test container or an external container.
+
+- Running tests in Jersey test container
+ mvn clean test
+
+- Running tests in an external container
+ build the test app
+ deploy to an external container
+ configure container connection info in jersey-spring-test/pom.xml, if needed
+ run tests in integration test mode:
+ mvn -Pit verify
+
+- Running tests in embedded Jetty instance
+ build the test app
+ deploy to Jetty:
+ mvn -Pjetty jetty:run
+ run tests in integration test mode in another console session:
+ mvn -Pit verify
+
+test class naming conventions
+- *ITTest.java: run in unit and IT test mode
+- *Test.java: run as unit tests
+- *IT.java: run as IT tests
+
diff --git a/tests/integration/spring4/pom.xml b/tests/integration/spring4/pom.xml
new file mode 100644
index 0000000..c5e93ab
--- /dev/null
+++ b/tests/integration/spring4/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.26-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>spring4</artifactId>
+
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-spring4</name>
+
+ <description>
+ Jersey tests for Spring 4 integration
+ </description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>${servlet2.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-spring4</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <configuration>
+ <webApp>
+ <contextPath>/</contextPath>
+ <webInfIncludeJarPattern>.*\.jar$</webInfIncludeJarPattern>
+ </webApp>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>delayed-strategy-skip-test</id>
+ <activation>
+ <property>
+ <name>org.glassfish.jersey.injection.manager.strategy</name>
+ <value>delayed</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountJerseyResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountJerseyResource.java
new file mode 100644
index 0000000..80af7bb
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountJerseyResource.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.math.BigDecimal;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+/**
+ * Jersey managed JAX-RS resource for testing jersey-spring.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+@Path("/jersey/account")
+public class AccountJerseyResource {
+
+ @Inject
+ @Named("AccountService-singleton")
+ private AccountService accountServiceInject;
+
+ @Autowired
+ @Qualifier("AccountService-singleton")
+ private AccountService accountServiceAutowired;
+
+ @Inject
+ @Named("AccountService-request-1")
+ private AccountService accountServiceRequest1;
+
+ @Autowired
+ @Qualifier("AccountService-request-1")
+ private AccountService accountServiceRequest2;
+
+ @Autowired
+ @Qualifier("AccountService-prototype-1")
+ private AccountService accountServicePrototype1;
+
+ @Autowired
+ @Qualifier("AccountService-prototype-1")
+ private AccountService accountServicePrototype2;
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Inject
+ private HK2ServiceSingleton hk2Singleton;
+
+ @Inject
+ private HK2ServiceRequestScoped hk2RequestScoped;
+
+ @Inject
+ private HK2ServicePerLookup hk2PerLookup;
+
+ private String message = "n/a";
+
+ // resource methods for testing resource class scope
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(final String message) {
+ this.message = message;
+ return message;
+ }
+
+ // JERSEY-2506 FIX VERIFICATION
+ @GET
+ @Path("server")
+ public String verifyServletRequestInjection() {
+ return "PASSED: " + httpServletRequest.getServerName();
+ }
+
+ @GET
+ @Path("singleton/server")
+ public String verifyServletRequestInjectionIntoSingleton() {
+ return accountServiceInject.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("singleton/autowired/server")
+ public String verifyServletRequestInjectionIntoAutowiredSingleton() {
+ return accountServiceAutowired.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("request/server")
+ public String verifyServletRequestInjectionIntoRequestScopedBean() {
+ return accountServiceRequest1.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("prototype/server")
+ public String verifyServletRequestInjectionIntoPrototypeScopedBean() {
+ return accountServicePrototype1.verifyServletRequestInjection();
+ }
+
+ // resource methods for testing singleton scoped beans
+ @GET
+ @Path("singleton/inject/{accountId}")
+ public BigDecimal getAccountBalanceSingletonInject(@PathParam("accountId") final String accountId) {
+ return accountServiceInject.getAccountBalance(accountId);
+ }
+
+ @GET
+ @Path("singleton/autowired/{accountId}")
+ public BigDecimal getAccountBalanceSingletonAutowired(@PathParam("accountId") final String accountId) {
+ return accountServiceAutowired.getAccountBalance(accountId);
+ }
+
+ @PUT
+ @Path("singleton/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public void setAccountBalanceSingleton(@PathParam("accountId") final String accountId, final String balance) {
+ accountServiceInject.setAccountBalance(accountId, new BigDecimal(balance));
+ }
+
+ // resource methods for testing request scoped beans
+ @PUT
+ @Path("request/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public BigDecimal setAccountBalanceRequest(@PathParam("accountId") final String accountId, final String balance) {
+ accountServiceRequest1.setAccountBalance(accountId, new BigDecimal(balance));
+ return accountServiceRequest2.getAccountBalance(accountId);
+ }
+
+ // resource methods for testing prototype scoped beans
+ @PUT
+ @Path("prototype/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public BigDecimal setAccountBalancePrototype(@PathParam("accountId") final String accountId, final String balance) {
+ accountServicePrototype1.setAccountBalance(accountId, new BigDecimal(balance));
+ return accountServicePrototype2.getAccountBalance(accountId);
+ }
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountService.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountService.java
new file mode 100644
index 0000000..851e215
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.math.BigDecimal;
+
+/**
+ * Simple account service to testify injection into different scopes.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public interface AccountService {
+
+ void setAccountBalance(String accountId, BigDecimal balance);
+
+ BigDecimal getAccountBalance(String accountId);
+
+ String verifyServletRequestInjection();
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountServiceImpl.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountServiceImpl.java
new file mode 100644
index 0000000..8b99e62
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountServiceImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * AccountService implementation.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class AccountServiceImpl implements AccountService {
+
+ private Map<String, BigDecimal> accounts = new HashMap<>();
+ private BigDecimal defaultAccountBalance;
+
+ // JERSEY-2506 FIX VERIFICATION
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Override
+ public void setAccountBalance(String accountId, BigDecimal balance) {
+ accounts.put(accountId, balance);
+ }
+
+ @Override
+ public BigDecimal getAccountBalance(String accountId) {
+ BigDecimal balance = accounts.get(accountId);
+ if (balance == null) {
+ return defaultAccountBalance;
+ }
+ return balance;
+ }
+
+ public void setDefaultAccountBalance(String defaultAccountBalance) {
+ this.defaultAccountBalance = new BigDecimal(defaultAccountBalance);
+ }
+
+ public String verifyServletRequestInjection() {
+ return "PASSED: " + httpServletRequest.getServerName();
+ }
+
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountSpringResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountSpringResource.java
new file mode 100644
index 0000000..6a6e6c2
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/AccountSpringResource.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.math.BigDecimal;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+/**
+ * Spring managed JAX-RS resource for testing jersey-spring.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+@Path("/spring/account")
+@Component
+public class AccountSpringResource {
+
+ @Inject
+ @Named("AccountService-singleton")
+ private AccountService accountServiceInject;
+
+ @Autowired
+ @Qualifier("AccountService-singleton")
+ private AccountService accountServiceAutowired;
+
+ @Inject
+ @Named("AccountService-request-1")
+ private AccountService accountServiceRequest1;
+
+ @Autowired
+ @Qualifier("AccountService-request-1")
+ private AccountService accountServiceRequest2;
+
+ @Autowired
+ @Qualifier("AccountService-prototype-1")
+ private AccountService accountServicePrototype1;
+
+ @Autowired
+ @Qualifier("AccountService-prototype-1")
+ private AccountService accountServicePrototype2;
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Inject
+ private HK2ServiceSingleton hk2Singleton;
+
+ @Inject
+ private HK2ServiceRequestScoped hk2RequestScoped;
+
+ @Inject
+ private HK2ServicePerLookup hk2PerLookup;
+
+ private String message = "n/a";
+
+ // resource methods for testing resource class scope
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(String message) {
+ this.message = message;
+ return message;
+ }
+
+ // JERSEY-2506 FIX VERIFICATION
+ @GET
+ @Path("server")
+ public String verifyServletRequestInjection() {
+ return "PASSED: " + httpServletRequest.getServerName();
+ }
+
+ @GET
+ @Path("singleton/server")
+ public String verifyServletRequestInjectionIntoSingleton() {
+ return accountServiceInject.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("singleton/autowired/server")
+ public String verifyServletRequestInjectionIntoAutowiredSingleton() {
+ return accountServiceAutowired.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("request/server")
+ public String verifyServletRequestInjectionIntoRequestScopedBean() {
+ return accountServiceRequest1.verifyServletRequestInjection();
+ }
+
+ @GET
+ @Path("prototype/server")
+ public String verifyServletRequestInjectionIntoPrototypeScopedBean() {
+ return accountServicePrototype1.verifyServletRequestInjection();
+ }
+
+ // resource methods for testing singleton scoped beans
+ @GET
+ @Path("singleton/inject/{accountId}")
+ public BigDecimal getAccountBalanceSingletonInject(@PathParam("accountId") String accountId) {
+ return accountServiceInject.getAccountBalance(accountId);
+ }
+
+ @GET
+ @Path("singleton/autowired/{accountId}")
+ public BigDecimal getAccountBalanceSingletonAutowired(@PathParam("accountId") String accountId) {
+ return accountServiceAutowired.getAccountBalance(accountId);
+ }
+
+ @PUT
+ @Path("singleton/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public void setAccountBalanceSingleton(@PathParam("accountId") String accountId, String balance) {
+ accountServiceInject.setAccountBalance(accountId, new BigDecimal(balance));
+ }
+
+ // resource methods for testing request scoped beans
+ @PUT
+ @Path("request/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public BigDecimal setAccountBalanceRequest(@PathParam("accountId") String accountId, String balance) {
+ accountServiceRequest1.setAccountBalance(accountId, new BigDecimal(balance));
+ return accountServiceRequest2.getAccountBalance(accountId);
+ }
+
+ // resource methods for testing prototype scoped beans
+ @PUT
+ @Path("prototype/{accountId}")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public BigDecimal setAccountBalancePrototype(@PathParam("accountId") String accountId, String balance) {
+ accountServicePrototype1.setAccountBalance(accountId, new BigDecimal(balance));
+ return accountServicePrototype2.getAccountBalance(accountId);
+ }
+
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ControllerResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ControllerResource.java
new file mode 100644
index 0000000..7714c22
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ControllerResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.stereotype.Controller;
+
+/**
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+@Controller
+@Path("/spring/controller")
+public class ControllerResource {
+
+ private String message;
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(final String message) {
+ this.message = message;
+ return message;
+ }
+
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/Endpoint.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/Endpoint.java
new file mode 100644
index 0000000..da9f170
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/Endpoint.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Component
+public @interface Endpoint {
+
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/EndpointResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/EndpointResource.java
new file mode 100644
index 0000000..9af0858
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/EndpointResource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+@Endpoint
+@Path("/spring/endpoint")
+public class EndpointResource {
+
+ private String message;
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(final String message) {
+ this.message = message;
+ return message;
+ }
+
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServicePerLookup.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServicePerLookup.java
new file mode 100644
index 0000000..ff689c6
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServicePerLookup.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+/**
+ * Type to be handled as HK2 per-lookup bean.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class HK2ServicePerLookup {
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceRequestScoped.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceRequestScoped.java
new file mode 100644
index 0000000..da45aea
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceRequestScoped.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+/**
+ * Type to be handled as HK2 request scoped bean.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class HK2ServiceRequestScoped {
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceSingleton.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceSingleton.java
new file mode 100644
index 0000000..a7b8fa8
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/HK2ServiceSingleton.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+/**
+ * Type to be handled as HK2 singleton.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class HK2ServiceSingleton {
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/MyApplication.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/MyApplication.java
new file mode 100644
index 0000000..568f30f
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/MyApplication.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.core.Application;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.PerLookup;
+import org.glassfish.jersey.process.internal.RequestScoped;
+
+/**
+ * JAX-RS application class for configuring injectable services in HK2 registry for testing purposes.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class MyApplication extends Application {
+
+ @Inject
+ public MyApplication(final InjectionManager injectionManager) {
+ Binder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindAsContract(HK2ServiceSingleton.class).in(Singleton.class);
+ bindAsContract(HK2ServiceRequestScoped.class).in(RequestScoped.class);
+ bindAsContract(HK2ServicePerLookup.class).in(PerLookup.class);
+ }
+ };
+
+ injectionManager.register(binder);
+ }
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/RepositoryResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/RepositoryResource.java
new file mode 100644
index 0000000..8c3b563
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/RepositoryResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+@Repository
+@Path("/spring/repository")
+public class RepositoryResource {
+
+ private String message;
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(final String message) {
+ this.message = message;
+ return message;
+ }
+
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ServiceResource.java b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ServiceResource.java
new file mode 100644
index 0000000..3516dcf
--- /dev/null
+++ b/tests/integration/spring4/src/main/java/org/glassfish/jersey/server/spring/test/ServiceResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+@Service
+@Path("/spring/service")
+public class ServiceResource {
+
+ private String message;
+
+ @PUT
+ @Path("message")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public String setMessage(final String message) {
+ this.message = message;
+ return message;
+ }
+
+ @GET
+ @Path("message")
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/integration/spring4/src/main/resources/applicationContext.xml b/tests/integration/spring4/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..0cc9127
--- /dev/null
+++ b/tests/integration/spring4/src/main/resources/applicationContext.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop
+ http://www.springframework.org/schema/aop/spring-aop.xsd">
+
+ <!--<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>-->
+ <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
+ <property name="autowiredAnnotationTypes">
+ <set>
+ <value>org.springframework.beans.factory.annotation.Autowired</value>
+ <value>org.springframework.beans.factory.annotation.Value</value>
+ </set>
+ </property>
+ </bean>
+
+ <bean name="AccountService-singleton" class="org.glassfish.jersey.server.spring.test.AccountServiceImpl" />
+
+ <bean name="AccountService-request-1" class="org.glassfish.jersey.server.spring.test.AccountServiceImpl" scope="request">
+ <aop:scoped-proxy/>
+ </bean>
+
+ <bean name="AccountService-request-2" class="org.glassfish.jersey.server.spring.test.AccountServiceImpl" scope="request"/>
+
+ <bean name="AccountService-prototype-1" class="org.glassfish.jersey.server.spring.test.AccountServiceImpl" scope="prototype">
+ <property name="defaultAccountBalance" value="987.65"/>
+ </bean>
+
+ <bean name="AccountService-prototype-2" class="org.glassfish.jersey.server.spring.test.AccountServiceImpl" scope="prototype"/>
+
+ <!-- Spring managed JAX-RS resources -->
+ <bean class="org.glassfish.jersey.server.spring.test.AccountSpringResource"/>
+
+ <bean class="org.glassfish.jersey.server.spring.test.ServiceResource"/>
+
+ <bean class="org.glassfish.jersey.server.spring.test.ControllerResource"/>
+
+ <bean class="org.glassfish.jersey.server.spring.test.RepositoryResource"/>
+
+ <bean class="org.glassfish.jersey.server.spring.test.EndpointResource"/>
+
+</beans>
diff --git a/tests/integration/spring4/src/main/webapp/WEB-INF/web.xml b/tests/integration/spring4/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c3cff9d
--- /dev/null
+++ b/tests/integration/spring4/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+
+ <module-name>jersey-spring-test</module-name>
+
+ <!-- use this to explicitly configure Spring -->
+ <!--
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+ <listener>
+ <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
+ </listener>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath:/applicationContext.xml</param-value>
+ </context-param>
+ -->
+
+ <servlet>
+ <servlet-name>org.glassfish.jersey.server.spring.test.MyApplication</servlet-name>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>org.glassfish.jersey.server.spring.test.MyApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+
+</web-app>
+
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceITCase.java
new file mode 100644
index 0000000..c9f9f17
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceITCase.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class AccountResourceITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new Application();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ final String r = target().path("/jersey/account/message").request().get(String.class);
+ assertEquals(r, "n/a");
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceTestBase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceTestBase.java
new file mode 100644
index 0000000..5c7774b
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/AccountResourceTestBase.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import java.math.BigDecimal;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Base class for JAX-RS resource tests.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public abstract class AccountResourceTestBase extends ResourceTestBase {
+
+ // test singleton scoped Spring bean injection using @Inject + @Autowired
+ @Test
+ public void testSingletonScopedSpringService() {
+ final BigDecimal newBalance = new BigDecimal(Math.random());
+ final WebTarget t = target(getResourceFullPath());
+
+ t.path("/singleton/xyz123").request().put(Entity.entity(newBalance.toString(), MediaType.TEXT_PLAIN_TYPE));
+ final BigDecimal balance = t.path("/singleton/autowired/xyz123").request().get(BigDecimal.class);
+ assertEquals(newBalance, balance);
+ }
+
+ @Test
+ public void testRequestScopedSpringService() {
+ final BigDecimal newBalance = new BigDecimal(Math.random());
+ final WebTarget t = target(getResourceFullPath());
+ final BigDecimal balance = t.path("request/abc456").request().put(Entity.text(newBalance), BigDecimal.class);
+ assertEquals(newBalance, balance);
+ }
+
+ @Test
+ public void testPrototypeScopedSpringService() {
+ final BigDecimal newBalance = new BigDecimal(Math.random());
+ final WebTarget t = target(getResourceFullPath());
+ final BigDecimal balance = t.path("prototype/abc456").request().put(Entity.text(newBalance), BigDecimal.class);
+ assertEquals(new BigDecimal("987.65"), balance);
+ }
+
+ @Test
+ public void testServletInjection() {
+ final WebTarget t = target(getResourceFullPath());
+
+ String server = t.path("server").request().get(String.class);
+ assertThat(server, startsWith("PASSED: "));
+
+ server = t.path("singleton/server").request().get(String.class);
+ assertThat(server, startsWith("PASSED: "));
+
+ server = t.path("singleton/autowired/server").request().get(String.class);
+ assertThat(server, startsWith("PASSED: "));
+
+ server = t.path("request/server").request().get(String.class);
+ assertThat(server, startsWith("PASSED: "));
+
+ server = t.path("prototype/server").request().get(String.class);
+ assertThat(server, startsWith("PASSED: "));
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/JerseyManagedITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/JerseyManagedITCase.java
new file mode 100644
index 0000000..4815e0e
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/JerseyManagedITCase.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Jersey managed JAX-RS resources.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class JerseyManagedITCase extends AccountResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(AccountJerseyResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/jersey/account";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals("n/a", msg);
+ }
+
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/ResourceTestBase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/ResourceTestBase.java
new file mode 100644
index 0000000..c460d7e
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/ResourceTestBase.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.SpringLifecycleListener;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+/**
+ * Base class for JAX-RS resource tests.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public abstract class ResourceTestBase extends JerseyTest {
+
+ private static final String TEST_WEBAPP_CONTEXT_PATH = "jersey.spring.test.contextPath";
+ private static final String TEST_CONTAINER_FACTORY_EXTERNAL = "org.glassfish.jersey.test.external"
+ + ".ExternalTestContainerFactory";
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Override
+ protected Application configure() {
+ final ResourceConfig rc = new ResourceConfig()
+ .register(SpringLifecycleListener.class)
+ .register(RequestContextFilter.class);
+ TestUtil.registerHK2Services(rc);
+ rc.property("contextConfigLocation", "classpath:applicationContext.xml");
+ return configure(rc);
+ }
+
+ protected abstract ResourceConfig configure(ResourceConfig rc);
+
+ protected abstract String getResourcePath();
+
+ protected String getResourceFullPath() {
+ final String containerFactory = System.getProperty(TestProperties.CONTAINER_FACTORY);
+ if (TEST_CONTAINER_FACTORY_EXTERNAL.equals(containerFactory)) {
+ return System.getProperty(TEST_WEBAPP_CONTEXT_PATH) + getResourcePath();
+ }
+ return getResourcePath();
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedControllerITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedControllerITCase.java
new file mode 100644
index 0000000..cbe42c6
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedControllerITCase.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Spring managed JAX-RS resources with @Controller archetype.
+ *
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+public class SpringManagedControllerITCase extends ResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(ControllerResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/spring/controller";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals(message, msg);
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedEndpointITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedEndpointITCase.java
new file mode 100644
index 0000000..fe96090
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedEndpointITCase.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Spring managed JAX-RS resources with custom composite
+ * annotation that derives from @Component.
+ *
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+public class SpringManagedEndpointITCase extends ResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(EndpointResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/spring/endpoint";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals(message, msg);
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedITCase.java
new file mode 100644
index 0000000..5eea429
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedITCase.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Spring managed JAX-RS resources.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class SpringManagedITCase extends AccountResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(AccountSpringResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/spring/account";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals(message, msg);
+ }
+
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedRepositoryITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedRepositoryITCase.java
new file mode 100644
index 0000000..5302a9e
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedRepositoryITCase.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Spring managed JAX-RS resources with @Repository archetype.
+ *
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+public class SpringManagedRepositoryITCase extends ResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(RepositoryResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/spring/repository";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals(message, msg);
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedServiceITCase.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedServiceITCase.java
new file mode 100644
index 0000000..633ceea
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/SpringManagedServiceITCase.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for Spring managed JAX-RS resources with @Service archetype.
+ *
+ * @author Konrad Garus (konrad.garus at gmail.com)
+ */
+public class SpringManagedServiceITCase extends ResourceTestBase {
+
+ @Override
+ protected ResourceConfig configure(final ResourceConfig rc) {
+ return rc.register(ServiceResource.class);
+ }
+
+ @Override
+ protected String getResourcePath() {
+ return "/spring/service";
+ }
+
+ @Test
+ public void testResourceScope() {
+ final WebTarget t = target(getResourceFullPath());
+ final String message = "hello, world";
+ final String echo = t.path("message").request().put(Entity.text(message), String.class);
+ assertEquals(message, echo);
+ final String msg = t.path("message").request().get(String.class);
+ assertEquals(message, msg);
+ }
+}
diff --git a/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/TestUtil.java b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/TestUtil.java
new file mode 100644
index 0000000..e4b4143
--- /dev/null
+++ b/tests/integration/spring4/src/test/java/org/glassfish/jersey/server/spring/test/TestUtil.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.spring.test;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.PerLookup;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.hk2.utilities.BuilderHelper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+
+class TestUtil {
+
+ public static ResourceConfig registerHK2Services(final ResourceConfig rc) {
+ rc
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(BuilderHelper.link(HK2ServiceSingleton.class).in(Singleton.class).build());
+ }
+ })
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(BuilderHelper.link(HK2ServiceRequestScoped.class).in(RequestScoped.class).build());
+ }
+ })
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(BuilderHelper.link(HK2ServicePerLookup.class).in(PerLookup.class).build());
+ }
+ });
+ return rc;
+ }
+}
diff --git a/tests/integration/tracing-support/pom.xml b/tests/integration/tracing-support/pom.xml
new file mode 100644
index 0000000..82e08eb
--- /dev/null
+++ b/tests/integration/tracing-support/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>tracing-support</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-tracing-support</name>
+
+ <description>Tracing support integration test</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <!-- client side config works - failsafe plugin forks jvm -->
+ <java.util.logging.config.file>${project.build.testOutputDirectory}/logging.properties</java.util.logging.config.file>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <configuration>
+ <connectors>
+ <connector>
+ <responseHeaderSize>16192</responseHeaderSize>
+ </connector>
+ </connectors>
+ <!-- server side config does not fork with jetty:run goal - it uses same jvm
+ use maven '-D' option instead:
+ mvn _goal_ -Djava.util.logging.config.file=target/test-classes/logging.properties
+ <systemProperties>
+ <systemProperty>
+ <name>java.util.logging.config.file</name>
+ <value>${project.build.testOutputDirectory}/logging.properties</value>
+ </systemProperty>
+ </systemProperties>
+ -->
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupport.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupport.java
new file mode 100644
index 0000000..f260a39
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.TracingConfig;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/ALL")
+public class AllTracingSupport extends TracingSupport {
+
+ public AllTracingSupport() {
+ super(TracingConfig.ALL);
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncResource.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncResource.java
new file mode 100644
index 0000000..338172c
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncResource.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+/**
+* @author Libor Kramolis (libor.kramolis at oracle.com)
+*/
+@Path("/async")
+public class AsyncResource {
+
+ @Path("{name}")
+ @GET
+ public void get(@PathParam("name") String name, @Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new Message(new StringBuffer(name).reverse().toString()));
+ }
+
+ @POST
+ public void post(Message post, @Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new Message(new StringBuffer(post.getText()).reverse().toString()));
+ }
+
+ @Path("sub-resource-method")
+ @POST
+ public void postSub(Message post, @Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new Message(new StringBuffer(post.getText()).reverse().toString()));
+ }
+
+ @Path("sub-resource-locator")
+ public AsyncSubResource getSubLoc() {
+ return new AsyncSubResource();
+ }
+
+ @Path("sub-resource-locator-null")
+ public AsyncSubResource getSubLocNull() {
+ return null;
+ }
+
+ @GET
+ @Path("runtime-exception")
+ public void getRuntimeException(@Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new RuntimeException("Something does not work ..."));
+ }
+
+ @GET
+ @Path("mapped-exception")
+ public void getMappedException(@Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new TestException("This could be client fault ..."));
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncSubResource.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncSubResource.java
new file mode 100644
index 0000000..9666448
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AsyncSubResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+
+/**
+* @author Libor Kramolis (libor.kramolis at oracle.com)
+*/
+@Path("/")
+public class AsyncSubResource {
+ @POST
+ public void post(Message post, @Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new Message(new StringBuffer(post.getText()).reverse().toString()));
+ }
+
+ @Path("sub-resource-method")
+ @POST
+ public void postSub(Message post, @Suspended final AsyncResponse asyncResponse) {
+ asyncResponse.resume(new Message(new StringBuffer(post.getText()).reverse().toString()));
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilter68.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilter68.java
new file mode 100644
index 0000000..bbf688a
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilter68.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(68)
+public class ContainerRequestFilter68 implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ //System.out.println("*** ContainerRequestFilter68.filter");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilterNoPriority.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilterNoPriority.java
new file mode 100644
index 0000000..80c095c
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerRequestFilterNoPriority.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class ContainerRequestFilterNoPriority implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ //System.out.println("*** ContainerRequestFilterNoPriority.filter");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilter5001.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilter5001.java
new file mode 100644
index 0000000..f674354
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilter5001.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(5001)
+public class ContainerResponseFilter5001 implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ //System.out.println("*** ContainerResponseFilter5001.filter");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilterNoPriority.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilterNoPriority.java
new file mode 100644
index 0000000..381da17
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ContainerResponseFilterNoPriority.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+public class ContainerResponseFilterNoPriority implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ //System.out.println("*** ContainerResponseFilterNoPriority.filter");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Message.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Message.java
new file mode 100644
index 0000000..b8f4f6a
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Message.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Message {
+
+ private String text;
+
+ public Message() {
+ }
+
+ public Message(String text) {
+ //System.out.println("*** Message: |" + text + "|");
+ this.text = text;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Message message = (Message) o;
+
+ if (text != null ? !text.equals(message.text) : message.text != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return text != null ? text.hashCode() : 0;
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderGeneric.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderGeneric.java
new file mode 100644
index 0000000..4d93336
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderGeneric.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Consumes("*/*")
+public class MessageBodyReaderGeneric implements MessageBodyReader<Message> {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public Message readFrom(Class<Message> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException, WebApplicationException {
+ return null;
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderTestFormat.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderTestFormat.java
new file mode 100644
index 0000000..81d0941
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyReaderTestFormat.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Consumes(Utils.APPLICATION_X_JERSEY_TEST)
+public class MessageBodyReaderTestFormat implements MessageBodyReader<Message> {
+
+ boolean serverSide = true;
+
+ public MessageBodyReaderTestFormat() {
+ }
+
+ public MessageBodyReaderTestFormat(final boolean serverSide) {
+ this.serverSide = serverSide;
+ }
+
+ @Override
+ public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.isAssignableFrom(Message.class);
+ }
+
+ @Override
+ public Message readFrom(final Class<Message> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException, WebApplicationException {
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(entityStream, MessageUtils.getCharset(mediaType)));
+
+ final String line = reader.readLine();
+ if (line == null || !line.startsWith(Utils.FORMAT_PREFIX) || !line.endsWith(Utils.FORMAT_SUFFIX)) {
+ throw new WebApplicationException(
+ new IllegalArgumentException("Input content '" + line + "' is not in a valid format!"));
+ }
+ final String text = line.substring(Utils.FORMAT_PREFIX.length(), line.length() - Utils.FORMAT_SUFFIX.length());
+
+ if (serverSide) {
+ Utils.throwException(text, this,
+ Utils.TestAction.MESSAGE_BODY_READER_THROW_WEB_APPLICATION,
+ Utils.TestAction.MESSAGE_BODY_READER_THROW_PROCESSING,
+ Utils.TestAction.MESSAGE_BODY_READER_THROW_ANY);
+ }
+
+ return new Message(text);
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterGeneric.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterGeneric.java
new file mode 100644
index 0000000..4e295ba
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterGeneric.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Produces("*/*")
+public class MessageBodyWriterGeneric implements MessageBodyWriter<Message> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return false;
+ }
+
+ @Override
+ public long getSize(Message message, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Message message,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterTestFormat.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterTestFormat.java
new file mode 100644
index 0000000..6983d18
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/MessageBodyWriterTestFormat.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.message.MessageUtils;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Produces(Utils.APPLICATION_X_JERSEY_TEST)
+public class MessageBodyWriterTestFormat implements MessageBodyWriter<Message> {
+
+ boolean serverSide = true;
+
+ public MessageBodyWriterTestFormat() {
+ }
+
+ public MessageBodyWriterTestFormat(final boolean serverSide) {
+ this.serverSide = serverSide;
+ }
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.isAssignableFrom(Message.class);
+ }
+
+ @Override
+ public long getSize(final Message message, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final Message message, final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException, WebApplicationException {
+ if (serverSide) {
+ Utils.throwException(message.getText(), this,
+ Utils.TestAction.MESSAGE_BODY_WRITER_THROW_WEB_APPLICATION,
+ Utils.TestAction.MESSAGE_BODY_WRITER_THROW_PROCESSING,
+ Utils.TestAction.MESSAGE_BODY_WRITER_THROW_ANY);
+ }
+
+ final OutputStreamWriter writer = new OutputStreamWriter(entityStream, MessageUtils.getCharset(mediaType));
+ writer.write(Utils.FORMAT_PREFIX);
+ writer.write(message.getText());
+ writer.write(Utils.FORMAT_SUFFIX);
+ writer.flush();
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupport.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupport.java
new file mode 100644
index 0000000..0a15268
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.TracingConfig;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@ApplicationPath("/ON_DEMAND")
+public class OnDemandTracingSupport extends TracingSupport {
+
+ public OnDemandTracingSupport() {
+ super(TracingConfig.ON_DEMAND);
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter23.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter23.java
new file mode 100644
index 0000000..6cc32a9
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter23.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@PreMatching
+@Priority(23)
+public class PreMatchingContainerRequestFilter23 implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ //System.out.println("*** PreMatchingContainerRequestFilter23.filter");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter42.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter42.java
new file mode 100644
index 0000000..fa83983
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/PreMatchingContainerRequestFilter42.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@PreMatching
+@Priority(42)
+public class PreMatchingContainerRequestFilter42 implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ //System.out.println("*** PreMatchingContainerRequestFilter42.filter");
+ Utils.throwException(requestContext, this,
+ Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_WEB_APPLICATION,
+ Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_PROCESSING,
+ Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_ANY);
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor14.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor14.java
new file mode 100644
index 0000000..e37971c
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor14.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(14)
+public class ReaderInterceptor14 implements ReaderInterceptor {
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ //System.out.println("*** ReaderInterceptor14.aroundReadFrom: BEFORE");
+ try {
+ Thread.sleep(42);
+ } catch (InterruptedException e) {
+ }
+ try {
+ return context.proceed();
+ } finally {
+ try {
+ Thread.sleep(42);
+ } catch (InterruptedException e) {
+ }
+ //System.out.println("*** ReaderInterceptor14.aroundReadFrom: AFTER");
+ }
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor18.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor18.java
new file mode 100644
index 0000000..3d3f444
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/ReaderInterceptor18.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(18)
+public class ReaderInterceptor18 implements ReaderInterceptor {
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ //System.out.println("*** ReaderInterceptor18.aroundReadFrom: BEFORE");
+ try {
+ return context.proceed();
+ } finally {
+ //System.out.println("*** ReaderInterceptor18.aroundReadFrom: AFTER");
+ }
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Resource.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Resource.java
new file mode 100644
index 0000000..c13b57d
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Resource.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+/**
+* @author Libor Kramolis (libor.kramolis at oracle.com)
+*/
+@Path("/root")
+public class Resource {
+
+ @Path("{name}")
+ @GET
+ public Message get(@PathParam("name") String name) {
+ return new Message(new StringBuffer(name).reverse().toString());
+ }
+
+ @POST
+ public Message post(Message post) {
+ return new Message(new StringBuffer(post.getText()).reverse().toString());
+ }
+
+ @Path("sub-resource-method")
+ @POST
+ public Message postSub(Message post) {
+ return new Message(new StringBuffer(post.getText()).reverse().toString());
+ }
+
+ @Path("sub-resource-locator")
+ public SubResource getSubLoc() {
+ return new SubResource();
+ }
+
+ @Path("sub-resource-locator-null")
+ public SubResource getSubLocNull() {
+ return null;
+ }
+
+ @GET
+ @Path("runtime-exception")
+ public Message getRuntimeException() {
+ throw new RuntimeException("Something does not work ...");
+ }
+
+ @GET
+ @Path("mapped-exception")
+ public Message getMappedException() {
+ throw new TestException("This could be client fault ...");
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/SubResource.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/SubResource.java
new file mode 100644
index 0000000..b803c3e
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/SubResource.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+/**
+* @author Libor Kramolis (libor.kramolis at oracle.com)
+*/
+@Path("/")
+public class SubResource {
+ @POST
+ public Message post(Message post) {
+ return new Message(new StringBuffer(post.getText()).reverse().toString());
+ }
+
+ @Path("sub-resource-method")
+ @POST
+ public Message postSub(Message post) {
+ return new Message(new StringBuffer(post.getText()).reverse().toString());
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestException.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestException.java
new file mode 100644
index 0000000..26dccfd
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TestException extends RuntimeException {
+
+ public TestException() {
+ super();
+ }
+
+ public TestException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExceptionMapper.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExceptionMapper.java
new file mode 100644
index 0000000..04d6dec
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExceptionMapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Priority(Priorities.USER)
+@Provider
+public class TestExceptionMapper implements ExceptionMapper<TestException> {
+
+ @Override
+ public Response toResponse(TestException throwable) {
+ return Response.status(501).build();
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperGeneric.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperGeneric.java
new file mode 100644
index 0000000..6a0cc9d
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperGeneric.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.Priorities;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.spi.ExtendedExceptionMapper;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Priority(Priorities.USER + 1)
+@Provider
+public class TestExtendedExceptionMapperGeneric implements ExtendedExceptionMapper<Exception> {
+
+ @Override
+ public Response toResponse(Exception throwable) {
+ return Response.status(500).build();
+ }
+
+ @Override
+ public boolean isMappable(Exception throwable) {
+ return !(throwable instanceof RuntimeException);
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperRuntime.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperRuntime.java
new file mode 100644
index 0000000..0161b37
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TestExtendedExceptionMapperRuntime.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+
+import javax.annotation.Priority;
+
+import org.glassfish.jersey.spi.ExtendedExceptionMapper;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Priority(Priorities.USER + 2)
+@Provider
+public class TestExtendedExceptionMapperRuntime implements ExtendedExceptionMapper<Throwable> {
+
+ @Override
+ public Response toResponse(Throwable throwable) {
+ return Response.status(500).build();
+ }
+
+ @Override
+ public boolean isMappable(Throwable throwable) {
+ return (throwable instanceof RuntimeException) && !(throwable instanceof WebApplicationException);
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TracingSupport.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TracingSupport.java
new file mode 100644
index 0000000..fabb7a2
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TracingSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.TracingConfig;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class TracingSupport extends ResourceConfig {
+
+ public TracingSupport(TracingConfig type) {
+ Utils.configure(this);
+ property(ServerProperties.TRACING, type.name());
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Utils.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Utils.java
new file mode 100644
index 0000000..aa9b45d
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/Utils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Configurable;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public final class Utils {
+
+ public static final String HEADER_TRACING_PREFIX = "X-Jersey-Tracing-";
+
+ public static final String APPLICATION_X_JERSEY_TEST = "application/x-jersey-test";
+ public static final String FORMAT_PREFIX = "-=#[";
+ public static final String FORMAT_SUFFIX = "]#=-";
+ public static final String HEADER_TEST_ACTION = "test-action";
+
+ private Utils() {
+ }
+
+ public static void configure(ResourceConfig configurable) {
+ configurable.packages(Utils.class.getPackage().getName());
+// OR:
+// configure((Configurable)configurable);
+// configurable.register(PreMatchingContainerRequestFilter23.class);
+// configurable.register(PreMatchingContainerRequestFilter42.class);
+// configurable.register(ContainerRequestFilter68.class);
+// configurable.register(ContainerRequestFilterNoPriority.class);
+// configurable.register(ContainerResponseFilter5001.class);
+// configurable.register(ContainerResponseFilterNoPriority.class);
+// configurable.register(TestExceptionMapper.class);
+// configurable.register(TestExtendedExceptionMapperGeneric.class);
+// configurable.register(TestExtendedExceptionMapperRuntime.class);
+// configurable.register(Resource.class);
+// configurable.register(SubResource.class);
+ configurable.register(new LoggingFeature(Logger.getAnonymousLogger(), LoggingFeature.Verbosity.PAYLOAD_ANY));
+ }
+
+ public static void configure(ClientConfig configurable) {
+ configure((Configurable) configurable);
+ }
+
+ public static void configure(Configurable configurable) {
+ configurable.register(ReaderInterceptor14.class);
+ configurable.register(ReaderInterceptor18.class);
+ configurable.register(WriterInterceptor39.class);
+ configurable.register(WriterInterceptor45.class);
+ configurable.register(new MessageBodyReaderTestFormat(false));
+ configurable.register(MessageBodyReaderGeneric.class);
+ configurable.register(new MessageBodyWriterTestFormat(false));
+ configurable.register(MessageBodyWriterGeneric.class);
+ }
+
+ public static void throwException(final ContainerRequestContext requestContext,
+ final Object fromContext,
+ final TestAction throwWebApplicationException,
+ final TestAction throwProcessingException,
+ final TestAction throwAnyException) {
+ final Utils.TestAction testAction = Utils.getTestAction(requestContext);
+ throwExceptionImpl(testAction, fromContext, throwWebApplicationException, throwProcessingException, throwAnyException);
+ }
+
+ public static void throwException(final String testActionName,
+ final Object fromContext,
+ final TestAction throwWebApplicationException,
+ final TestAction throwProcessingException,
+ final TestAction throwAnyException) {
+ Utils.TestAction testAction;
+ try {
+ testAction = TestAction.valueOf(testActionName);
+ } catch (IllegalArgumentException ex) {
+ try {
+ testAction = TestAction.valueOf(new StringBuffer(testActionName).reverse().toString());
+ } catch (IllegalArgumentException ex2) {
+ testAction = null;
+ }
+ }
+ throwExceptionImpl(testAction, fromContext, throwWebApplicationException, throwProcessingException, throwAnyException);
+ }
+
+ private static void throwExceptionImpl(final Utils.TestAction testAction,
+ final Object fromContext,
+ final TestAction throwWebApplicationException,
+ final TestAction throwProcessingException,
+ final TestAction throwAnyException) {
+ final String message = "Test Exception from " + fromContext.getClass().getName();
+ if (testAction == null) {
+ // do nothing
+ } else if (testAction == throwWebApplicationException) {
+ throw new WebApplicationException(message);
+ } else if (testAction == throwProcessingException) {
+ throw new ProcessingException(message);
+ } else if (testAction == throwAnyException) {
+ throw new RuntimeException(message);
+ }
+ }
+
+ public static TestAction getTestAction(ContainerRequestContext requestContext) {
+ String testActionHeader = requestContext.getHeaderString(HEADER_TEST_ACTION);
+ TestAction testAction = null;
+ if (testActionHeader != null) {
+ testAction = TestAction.valueOf(testActionHeader);
+ }
+ return testAction;
+ }
+
+ public static enum TestAction {
+ PRE_MATCHING_REQUEST_FILTER_THROW_WEB_APPLICATION,
+ PRE_MATCHING_REQUEST_FILTER_THROW_PROCESSING,
+ PRE_MATCHING_REQUEST_FILTER_THROW_ANY,
+ MESSAGE_BODY_READER_THROW_WEB_APPLICATION,
+ MESSAGE_BODY_READER_THROW_PROCESSING,
+ MESSAGE_BODY_READER_THROW_ANY,
+ MESSAGE_BODY_WRITER_THROW_WEB_APPLICATION,
+ MESSAGE_BODY_WRITER_THROW_PROCESSING,
+ MESSAGE_BODY_WRITER_THROW_ANY;
+ //TODO add other *_THROW_* actions to throw exception from other stages
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor39.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor39.java
new file mode 100644
index 0000000..f6257db
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor39.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.util.Date;
+import javax.annotation.Priority;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(39)
+public class WriterInterceptor39 implements WriterInterceptor {
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ //System.out.println("*** WriterInterceptor39.aroundWriteTo: BEFORE");
+ try {
+ Thread.sleep(42);
+ } catch (InterruptedException e) {
+ }
+ context.getHeaders().putSingle(WriterInterceptor39.class.getSimpleName(), new Date());
+ context.proceed();
+ //System.out.println("*** WriterInterceptor39.aroundWriteTo: AFTER");
+ }
+}
diff --git a/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor45.java b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor45.java
new file mode 100644
index 0000000..a76f13f
--- /dev/null
+++ b/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/WriterInterceptor45.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.util.Date;
+import javax.annotation.Priority;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Provider
+@Priority(45)
+public class WriterInterceptor45 implements WriterInterceptor {
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ //System.out.println("*** WriterInterceptor45.aroundWriteTo: BEFORE");
+ context.getHeaders().putSingle(WriterInterceptor45.class.getSimpleName(), new Date());
+ context.proceed();
+ try {
+ Thread.sleep(42);
+ } catch (InterruptedException e) {
+ }
+ //System.out.println("*** WriterInterceptor45.aroundWriteTo: AFTER");
+ }
+}
diff --git a/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupportITCase.java b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupportITCase.java
new file mode 100644
index 0000000..430789e
--- /dev/null
+++ b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupportITCase.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.TracingConfig;
+import org.glassfish.jersey.server.internal.ServerTraceEvent;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * 'ALL' tracing support test that is running in external Jetty container.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(Parameterized.class)
+public class AllTracingSupportITCase extends JerseyTest {
+
+ private final String resourcePath;
+
+ public AllTracingSupportITCase(String resourcePath) {
+ this.resourcePath = resourcePath;
+ }
+
+ @Parameterized.Parameters(name = "{index}: {0}")
+ public static List<Object[]> testData() {
+ return Arrays.asList(new Object[][] {
+ {"/root"},
+ {"/async"},
+ });
+ }
+
+ //
+ // JerseyTest
+ //
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return new AllTracingSupport();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig clientConfig) {
+ Utils.configure(clientConfig);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ //
+ // tests
+ //
+
+ @Test
+ public void testGet() {
+ Invocation.Builder builder = resource(resourcePath).path("NAME").request();
+ Response response = builder.get();
+ assertXJerseyTrace(response, false);
+ assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testRuntimeException() {
+ Invocation.Builder builder = resource(resourcePath).path("runtime-exception").request();
+
+ Response response = builder.get();
+ assertXJerseyTrace(response, true);
+ assertEquals(500, response.getStatus());
+ }
+
+ @Test
+ public void testMappedException() throws InterruptedException, IOException {
+ Invocation.Builder builder = resource(resourcePath).path("mapped-exception").request();
+
+ Response response = builder.get();
+ assertXJerseyTrace(response, true);
+ assertEquals(501, response.getStatus());
+ }
+
+ @Test
+ public void testGet405() {
+ Invocation.Builder builder = resource(resourcePath).request();
+
+ Response response = builder.get();
+ assertXJerseyTrace(response, false);
+ assertEquals(405, response.getStatus());
+ }
+
+ @Test
+ public void testPostSubResourceMethod() {
+ Invocation.Builder builder = resource(resourcePath).path("sub-resource-method").request();
+
+ Response response = builder.post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertXJerseyTrace(response, false);
+ assertEquals("TSOP", response.readEntity(Message.class).getText());
+ }
+
+ @Test
+ public void testPostSubResourceLocator() {
+ Invocation.Builder builder = resource(resourcePath).path("sub-resource-locator").request();
+
+ Response response = builder.post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertXJerseyTrace(response, false);
+ assertEquals("TSOP", response.readEntity(Message.class).getText());
+ }
+
+ @Test
+ public void testPostSubResourceLocatorNull() {
+ Invocation.Builder builder = resource(resourcePath).path("sub-resource-locator-null").request();
+
+ Response response = builder.post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertEquals(404, response.getStatus());
+ }
+
+ @Test
+ public void testPostSubResourceLocatorSubResourceMethod() {
+ Invocation.Builder builder = resource(resourcePath).path("sub-resource-locator").path("sub-resource-method").request();
+
+ Response response = builder.post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertXJerseyTrace(response, false);
+ assertEquals("TSOP", response.readEntity(Message.class).getText());
+ }
+
+ @Test
+ public void testTraceInnerException() {
+ // PRE_MATCHING_REQUEST_FILTER
+ testTraceInnerExceptionImpl(Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_WEB_APPLICATION, 500, false);
+ testTraceInnerExceptionImpl(Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_PROCESSING, 500, true);
+ testTraceInnerExceptionImpl(Utils.TestAction.PRE_MATCHING_REQUEST_FILTER_THROW_ANY, 500, true);
+ // MESSAGE_BODY_WRITER
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_WRITER_THROW_WEB_APPLICATION, 500, false);
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_WRITER_THROW_PROCESSING, 500, true);
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_WRITER_THROW_ANY, 500, true);
+ // MESSAGE_BODY_READER
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_READER_THROW_WEB_APPLICATION, 500, false);
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_READER_THROW_PROCESSING, 500, true);
+ testTraceInnerExceptionImpl(Utils.TestAction.MESSAGE_BODY_READER_THROW_ANY, 500, true);
+ }
+
+ //
+ // utils
+ //
+
+ private void testTraceInnerExceptionImpl(Utils.TestAction testAction, int expectedStatus, boolean exceptionExpected) {
+ Invocation.Builder builder = resource(resourcePath).request();
+ builder.header(Utils.HEADER_TEST_ACTION, testAction);
+
+ Response response = builder.post(Entity.entity(new Message(testAction.name()), Utils.APPLICATION_X_JERSEY_TEST));
+ assertXJerseyTrace(response, exceptionExpected);
+ assertEquals(expectedStatus, response.getStatus());
+ }
+
+ private void assertXJerseyTrace(Response response, boolean exceptionExpected) {
+ int finished = 0;
+ int exceptionMapping = 0;
+
+ for (String k : response.getHeaders().keySet()) {
+ if (k.toLowerCase().startsWith(Utils.HEADER_TRACING_PREFIX.toLowerCase())) {
+ String value = response.getHeaderString(k);
+ if (value.startsWith(ServerTraceEvent.FINISHED.category())) {
+ finished++;
+ } else if (value.startsWith(ServerTraceEvent.EXCEPTION_MAPPING.category())) {
+ exceptionMapping++;
+ }
+ }
+ }
+ assertEquals("Just one FINISHED expected!", 1, finished);
+ if (exceptionExpected) {
+ assertEquals("EXCEPTION expected!", 1, exceptionMapping);
+ } else {
+ assertEquals("EXCEPTION NOT expected!", 0, exceptionMapping);
+ }
+ }
+
+ private WebTarget resource(String path) {
+ return target("/" + TracingConfig.ALL).path(path);
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupportITCase.java b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupportITCase.java
new file mode 100644
index 0000000..05ecceb
--- /dev/null
+++ b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/OnDemandTracingSupportITCase.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.tracing;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.internal.TracingLogger;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.TracingConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * 'ON_DEMAND' tracing support test that is running in external Jetty container.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class OnDemandTracingSupportITCase extends JerseyTest {
+
+ //
+ // JerseyTest
+ //
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ return new OnDemandTracingSupport();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig clientConfig) {
+ Utils.configure(clientConfig);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ //
+ // tests
+ //
+
+ @Test
+ public void testNoTracing() {
+ Invocation.Builder builder = resource("/root").request();
+ Response response = builder.post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertFalse(hasX_Jersey_Trace(response));
+ assertEquals("TSOP", response.readEntity(Message.class).getText());
+ }
+
+ @Test
+ public void testTraceAcceptEmpty() {
+ testTraceAccept("");
+ }
+
+ @Test
+ public void testTraceAcceptTrue() {
+ testTraceAccept("true");
+ }
+
+ @Test
+ public void testTraceAcceptWhatever() {
+ testTraceAccept("whatever");
+ }
+
+ private void testTraceAccept(String acceptValue) {
+ Invocation.Builder builder = resource("/root").request();
+ Response response = builder.header(TracingLogger.HEADER_ACCEPT, acceptValue)
+ .post(Entity.entity(new Message("POST"), Utils.APPLICATION_X_JERSEY_TEST));
+ assertTrue(hasX_Jersey_Trace(response));
+ assertEquals("TSOP", response.readEntity(Message.class).getText());
+ }
+
+ //
+ // utils
+ //
+
+ private boolean hasX_Jersey_Trace(Response response) {
+ for (String k : response.getHeaders().keySet()) {
+ if (k.toLowerCase().startsWith(Utils.HEADER_TRACING_PREFIX.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private WebTarget resource(String path) {
+ return target("/" + TracingConfig.ON_DEMAND).path(path);
+ }
+
+}
diff --git a/tests/integration/tracing-support/src/test/resources/logging.properties b/tests/integration/tracing-support/src/test/resources/logging.properties
new file mode 100644
index 0000000..6ba7395
--- /dev/null
+++ b/tests/integration/tracing-support/src/test/resources/logging.properties
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+#All attributes details
+handlers=java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level=FINEST
+java.util.logging.SimpleFormatter.format=%4$-7s [%3$s] %5$s%6$s%n
+
+#All log level details
+.level=INFO
+org.glassfish.jersey.level=CONFIG
+org.glassfish.jersey.tracing.level=FINEST
diff --git a/tests/mem-leaks/pom.xml b/tests/mem-leaks/pom.xml
new file mode 100644
index 0000000..7a6b4c1
--- /dev/null
+++ b/tests/mem-leaks/pom.xml
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.memleaks</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-memleak</name>
+
+ <description>
+ Memory leaks test maven parent module.
+
+ This module aggregates maven based configuration for all memory leak related modules.
+
+ Note that the majority of plugin execution in maven sub-modules is bound to phase none by default. The reason is that
+ memory leak tests are executed only if one of memory leak maven profiles are activated.
+ </description>
+
+ <properties>
+
+ <memleak.jersey.version>2.28-SNAPSHOT</memleak.jersey.version>
+
+ <memleak.tmpdir>/tmp</memleak.tmpdir>
+
+ <memleak.jvm.maxheap>512m</memleak.jvm.maxheap>
+ <memleak.jvm.heapdumpdir>${project.build.directory}</memleak.jvm.heapdumpdir>
+
+ <external.container.factory>org.glassfish.jersey.test.external.ExternalTestContainerFactory</external.container.factory>
+ <external.container.port>${external.container.port.dynamic}</external.container.port>
+ <external.container.contextRoot>${project.artifactId}-${project.version}</external.container.contextRoot>
+ <external.container.warPath>${project.build.directory}/${project.build.finalName}.${project.packaging}
+ </external.container.warPath>
+ <external.container.logFile>${project.build.directory}/container.log</external.container.logFile>
+
+ <maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
+ <memleak.timestamp>${maven.build.timestamp}</memleak.timestamp>
+
+ <memleak.glassfish.zip>${memleak.tmpdir}/memleak-test-glassfish-${memleak.timestamp}.zip</memleak.glassfish.zip>
+ <memleak.glassfish.adminPort>${memleak.glassfish.adminPort.dynamic}</memleak.glassfish.adminPort>
+ <memleak.glassfish.url>${jersey.runner.distUrl}</memleak.glassfish.url>
+ <memleak.glassfish.maxheap>${memleak.jvm.maxheap}</memleak.glassfish.maxheap>
+
+ <memleak.wls.jar>${memleak.tmpdir}/memleak-test-wls-${memleak.timestamp}.jar</memleak.wls.jar>
+ <memleak.wls.url>${jersey.runner.distUrl}</memleak.wls.url>
+ <memleak.wls.maxheap>${memleak.jvm.maxheap}</memleak.wls.maxheap>
+
+ <memleak.tomcat.version>8.0.23</memleak.tomcat.version>
+ <memleak.tomcat.url>
+ http://archive.apache.org/dist/tomcat/tomcat-8/v${memleak.tomcat.version}/bin/apache-tomcat-${memleak.tomcat.version}.zip
+ </memleak.tomcat.url>
+ <memleak.tomcat.zip>${memleak.tmpdir}/memleak-test-tomcat-${memleak.tomcat.version}-${memleak.timestamp}.zip
+ </memleak.tomcat.zip>
+ <memleak.tomcat.maxheap>${memleak.jvm.maxheap}</memleak.tomcat.maxheap>
+
+ <!-- by default, all common executions are bound to the pahse 'none' so that they're not executed -->
+ <phase.common.pre-integration-test>none</phase.common.pre-integration-test>
+ <phase.common.post-integration-test>none</phase.common.post-integration-test>
+
+ <!-- by default, redeployment executions are bound to the phase 'none' so that they're not executed -->
+ <phase.redeployment.pre-integration-test>none</phase.redeployment.pre-integration-test>
+ <phase.redeployment.integration-test>none</phase.redeployment.integration-test>
+ <phase.redeployment.post-integration-test>none</phase.redeployment.post-integration-test>
+
+ <!-- by default, test-cases executions are bound to the phase 'none' so that they're not executed -->
+ <phase.tests.test>none</phase.tests.test>
+ <phase.tests.pre-integration-test>none</phase.tests.pre-integration-test>
+ <phase.tests.integration-test>none</phase.tests.integration-test>
+ <phase.tests.post-integration-test>none</phase.tests.post-integration-test>
+ <phase.tests.verify>none</phase.tests.verify>
+ </properties>
+
+ <modules>
+ <module>redeployment</module>
+ <module>test-cases</module>
+ </modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>reserve-network-ports</id>
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ <configuration>
+ <portNames>
+ <portName>external.container.port.dynamic</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <warPath>${external.container.warPath}</warPath>
+ <contextRoot>${external.container.contextRoot}</contextRoot>
+ <port>${external.container.port}</port>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ </build>
+
+ <profiles>
+ <profile>
+ <id>gf4</id>
+ <properties>
+ <external.container.logFile>
+ ${project.build.directory}/glassfish4/glassfish/domains/memleak_test_domain/logs/server.log
+ </external.container.logFile>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <configuration>
+ <portNames combine.children="append">
+ <portName>memleak.glassfish.adminPort.dynamic</portName>
+ </portNames>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <adminPort>${memleak.glassfish.adminPort}</adminPort>
+ <distUrl>${memleak.glassfish.url}</distUrl>
+ <distTargetLocation>${memleak.glassfish.zip}</distTargetLocation>
+ <distSubdir>glassfish4</distSubdir>
+ <maxHeap>${memleak.glassfish.maxheap}</maxHeap>
+ </configuration>
+ <executions>
+ <execution>
+ <id>gf4-download</id>
+ <goals>
+ <goal>downloadGf4</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>gf4-start-and-deploy</id>
+ <goals>
+ <goal>startAndDeployGf4</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>gf4-undeploy-and-stop</id>
+ <goals>
+ <goal>stopGf4</goal>
+ </goals>
+ <phase>${phase.common.post-integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ <profile>
+ <id>wls</id>
+ <properties>
+ <external.container.logFile>
+ ${project.build.directory}/wls12210/memleak_test_domain/wls.log
+ </external.container.logFile>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <configuration>
+ <distUrl>${memleak.wls.url}</distUrl>
+ <distTargetLocation>${memleak.wls.jar}</distTargetLocation>
+ <distSubdir>wls12210</distSubdir>
+ <maxHeap>${memleak.wls.maxheap}</maxHeap>
+ </configuration>
+ <executions>
+ <execution>
+ <id>wls-download</id>
+ <goals>
+ <goal>downloadWls</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>wls-deploy</id>
+ <goals>
+ <goal>startAndDeployWls</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>wls-stop</id>
+ <goals>
+ <goal>stopWls</goal>
+ </goals>
+ <phase>${phase.common.post-integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ <profile>
+ <id>tomcat</id>
+ <properties>
+ <external.container.logFile>
+ ${project.build.directory}/apache-tomcat-${memleak.tomcat.version}/logs/catalina.out
+ </external.container.logFile>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <configuration>
+ <distUrl>${memleak.tomcat.url}</distUrl>
+ <distTargetLocation>${memleak.tomcat.zip}</distTargetLocation>
+ <distSubdir>apache-tomcat-${memleak.tomcat.version}</distSubdir>
+ <maxHeap>${memleak.tomcat.maxheap}</maxHeap>
+ </configuration>
+ <executions>
+ <execution>
+ <id>tomcat-download</id>
+ <goals>
+ <goal>downloadTomcat</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>tomcat-deploy</id>
+ <goals>
+ <goal>startAndDeployTomcat</goal>
+ </goals>
+ <phase>${phase.common.pre-integration-test}</phase>
+ </execution>
+ <execution>
+ <id>tomcat-stop</id>
+ <goals>
+ <goal>stopTomcat</goal>
+ </goals>
+ <phase>${phase.common.post-integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+
+ <!-- profiles that help set ${memleak.tmpdir} based on environment -->
+ <profile>
+ <id>memleak-env-tmpdir</id>
+ <activation>
+ <property>
+ <name>env.TMPDIR</name>
+ </property>
+ </activation>
+ <properties>
+ <memleak.tmpdir>${env.TMPDIR}</memleak.tmpdir>
+ </properties>
+ </profile>
+ <profile>
+ <id>memleak-env-tmp</id>
+ <activation>
+ <property>
+ <name>env.TMP</name>
+ </property>
+ </activation>
+ <properties>
+ <memleak.tmpdir>${env.TMP}</memleak.tmpdir>
+ </properties>
+ </profile>
+
+ </profiles>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey</groupId>
+ <artifactId>jersey-bom</artifactId>
+ <version>${memleak.jersey.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+</project>
diff --git a/tests/mem-leaks/redeployment/pom.xml b/tests/mem-leaks/redeployment/pom.xml
new file mode 100644
index 0000000..af2f872
--- /dev/null
+++ b/tests/mem-leaks/redeployment/pom.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-memleak-redeployment</name>
+
+ <description>
+ Memory leaks redeployment test.
+
+ This module (and all sub-modules) combine container-runner-maven-plugin goals ('download', 'startAndDeploy', 'stop') with
+ 'redeploy' goal which repetitively redeploys and tests with a single http request the deployed application.
+
+ To build all the modules in the redeployment sub-module, run:
+
+ mvn clean install -amd -pl tests/mem-leaks/ -P tomcat,memleak-redeployment -fae
+ </description>
+
+ <properties>
+ <!-- by default, bound to 'none' phase; if 'memleak-redeployment' profile active, they're activated -->
+ <phase.common.pre-integration-test>${phase.redeployment.pre-integration-test}</phase.common.pre-integration-test>
+ <phase.common.post-integration-test>${phase.redeployment.post-integration-test}</phase.common.post-integration-test>
+ </properties>
+
+ <modules>
+ <module>redeployment-leaking-test-app</module>
+ <module>redeployment-hello-world-app-ref</module>
+ <module>redeployment-no-jersey-app</module>
+ <module>redeployment-threadlocals-app</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>memleak-redeployment</id>
+ <properties>
+ <!-- set all the phases for this sub-module tree so that the executions are un-bound from the 'none' phase -->
+ <phase.redeployment.pre-integration-test>pre-integration-test</phase.redeployment.pre-integration-test>
+ <phase.redeployment.integration-test>integration-test</phase.redeployment.integration-test>
+ <phase.redeployment.post-integration-test>post-integration-test</phase.redeployment.post-integration-test>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <configuration>
+ <!-- these three memleak.redeploy.* properties should be initialized by sub-modules -->
+ <expectedStatus>${memleak.redeploy.expectedStatus}</expectedStatus>
+ <redeployCount>${memleak.redeploy.count}</redeployCount>
+ <requestPathQuery>${memleak.redeploy.requestPathQuery}</requestPathQuery>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>custom-enforcer-rules</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>enforce-out-of-memory-did-not-occur</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <phase>${phase.redeployment.post-integration-test}</phase>
+ <configuration>
+ <rules>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.FilePatternDoesNotExistRule">
+ <files>
+ <file>${memleak.jvm.heapdumpdir}/java_pid*.hprof</file>
+ </files>
+ </rule>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.PatternNotMatchedInFileRule">
+ <file>${external.container.logFile}</file>
+ <pattern>.*java\.lang\.OutOfMemoryError.*</pattern>
+ </rule>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ <profile>
+ <id>wls</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>wls-redeploy</id>
+ <goals>
+ <goal>redeployWls</goal>
+ </goals>
+ <phase>${phase.redeployment.integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ <profile>
+ <id>gf4</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>gf4-redeploy</id>
+ <goals>
+ <goal>redeployGf4</goal>
+ </goals>
+ <phase>${phase.redeployment.integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ <profile>
+ <id>tomcat</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>tomcat-redeploy</id>
+ <goals>
+ <goal>redeployTomcat</goal>
+ </goals>
+ <phase>${phase.redeployment.integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
new file mode 100644
index 0000000..862fb6b
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>redeployment-hello-world-app-ref</artifactId>
+ <name>jersey-tests-memleak-redeployment-hello-world-app-ref</name>
+
+ <description>
+ Maven module that tests :helloworld-webapp:war in order to prevent regression of a problem where a repetitive redeployment
+ may have caused memory leaks.
+
+ To run this test, execute from Jersey root dir:
+
+ [1] Glassfish: mvn install -am -pl :redeployment-hello-world-app-ref -P gf4,memleak-redeployment
+
+ [2] Weblogic: mvn install -am -pl :redeployment-hello-world-app-ref -P wls,memleak-redeployment
+
+ [3] Tomcat: mvn install -am -pl :redeployment-hello-world-app-ref -P tomcat,memleak-redeployment
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>256m</memleak.jvm.maxheap>
+ <memleak.tomcat.maxheap>56m</memleak.tomcat.maxheap>
+
+ <external.container.warPath>${org.glassfish.jersey.examples:helloworld-webapp:war}</external.container.warPath>
+ <external.container.contextRoot>helloworld-webapp</external.container.contextRoot>
+
+ <memleak.redeploy.count>200</memleak.redeploy.count>
+ <memleak.redeploy.expectedStatus>200</memleak.redeploy.expectedStatus>
+ <memleak.redeploy.requestPathQuery>${external.container.contextRoot}/helloworld</memleak.redeploy.requestPathQuery>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>tomcat</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-threadlocals-left-cleaned</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <phase>${phase.redeployment.post-integration-test}</phase>
+ <configuration>
+ <!-- assure that Tomcat ThreadLocal memory leak detection messages weren't included in the Tomcat output.
+ If so, ThreadLocals aren't kept clean and that's what users do not like (see JERSEY-2890). -->
+ <rules>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.PatternNotMatchedInFileRule">
+ <file>${external.container.logFile}</file>
+ <pattern>
+ <![CDATA[.*SEVERE.*The web application.*created a ThreadLocal with key.*avoid a probable memory leak.*]]></pattern>
+ <maxMatchedLines>3</maxMatchedLines>
+ </rule>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>memleak-reproducer</id>
+ <properties>
+ <memleak.jersey.version>2.19</memleak.jersey.version>
+ </properties>
+ </profile>
+ </profiles>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>resolve-maven-dependencies</id>
+ <goals>
+ <goal>properties</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.examples</groupId>
+ <artifactId>helloworld-webapp</artifactId>
+ <type>war</type>
+ <version>2.28-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
new file mode 100644
index 0000000..951b572
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>redeployment-leaking-test-app</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-redeployment-leaking-test-app</name>
+
+ <description>
+ An example application that causes a memory leak in the container where it's being repetitively redeployed.
+
+
+ To run this example, execute from jersey root dir:
+
+ [1] Glassfish: mvn clean install -pl :redeployment-leaking-test-app -P gf4,memleak-leaking-test,memleak-redeployment
+
+ [2] Weblogic: mvn clean install -pl :redeployment-leaking-test-app -P wls,memleak-leaking-test,memleak-redeployment
+
+ [3] Tomcat: mvn clean install -pl :redeployment-leaking-test-app -P tomcat,memleak-leaking-test,memleak-redeployment
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>256m</memleak.jvm.maxheap>
+
+ <memleak.redeploy.count>100</memleak.redeploy.count>
+ <memleak.redeploy.expectedStatus>200</memleak.redeploy.expectedStatus>
+ <memleak.redeploy.requestPathQuery>${external.container.contextRoot}/invoke?size=20000000</memleak.redeploy.requestPathQuery>
+
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ <configuration>
+ <method>POST</method>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-out-of-memory-did-not-occur</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>memleak-leaking-test</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-out-of-memory-did-not-occur</id>
+ <phase>${phase.redeployment.post-integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/DaemonThreadMemoryLeakingResource.java b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/DaemonThreadMemoryLeakingResource.java
new file mode 100644
index 0000000..395de4b
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/DaemonThreadMemoryLeakingResource.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.testleak;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import javax.inject.Singleton;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+/**
+ * Resource that causes {@link OutOfMemoryError} exception upon repetitive call of {@link #invoke(int)} of an application that is
+ * being redeployed.
+ * <p/>
+ * The purpose of this resource (and the app) is to test whether the memory leaking infrastructure for redeployment scenarios
+ * works.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/")
+@Singleton
+public class DaemonThreadMemoryLeakingResource {
+
+ @POST
+ @Path("invoke")
+ public String invoke(@DefaultValue("1048576") @QueryParam("size") final int size) {
+
+ final Future<?> future = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(true).build())
+ .submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ System.out.println("Running a Thread!");
+ final int mbytes = size / (1024 * 1024);
+ final byte[][] bytes = new byte[mbytes][];
+ for (int i = 1; i <= mbytes; ++i) {
+ bytes[i - 1] = new byte[1024 * 1024];
+ System.out.println("Allocated: " + i + "MB!");
+ }
+
+ System.out.println("Memory allocated! Total: " + mbytes + "MB! Sleeping...");
+ for (int i = 0; i < 1000000; ++i) {
+ System.out.println("Thread " + Thread.currentThread() + " sleeping!");
+ Thread.sleep(10000);
+ }
+ System.out.println("Freeing: " + size + " of bytes. " + bytes);
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Thread Interrupted!", e);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw e;
+ }
+
+ }
+ });
+
+ System.out.println("Trying to allocate bytes from the thread itself.");
+ final byte[] bytes = new byte[size];
+ return "Future submitted: " + future + " bytes allocated: " + bytes;
+ }
+
+ @GET
+ @Path("hello")
+ @Produces("text/plain")
+ public String helloWorld() {
+ System.out.println("HELLO WORLD!");
+ return "HELLO WORLD!";
+ }
+
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java
new file mode 100644
index 0000000..4d68713
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.testleak;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(DaemonThreadMemoryLeakingResource.class);
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2b29bd3
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true">
+
+ <filter>
+ <filter-name>jersey</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.memleaks.testleak.TestApplication</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
new file mode 100644
index 0000000..f6f924b
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>redeployment-no-jersey-app</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-redeployment-no-jersey-app</name>
+
+ <description>
+ Reproducer of HK2-247, HK2-264
+
+ On some platforms, redeployment of this application does not cause a memory leak. However, several HK2 instances are left
+ in the container (referenced from ThreadLocals), which is what is tested (on Tomcat only).
+
+ [Execution commands]
+
+ Should not fail: mvn -pl :redeployment-no-jersey-app clean install -P tomcat,memleak-redeployment
+
+ Should fail: mvn -pl :redeployment-no-jersey-app clean install -P tomcat,memleak-redeployment,memleak-reproducer
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>192m</memleak.jvm.maxheap>
+ <external.container.contextRoot>no-jersey-service</external.container.contextRoot>
+
+ <memleak.redeploy.count>500</memleak.redeploy.count>
+ <memleak.redeploy.expectedStatus>200</memleak.redeploy.expectedStatus>
+ <memleak.redeploy.requestPathQuery>${external.container.contextRoot}</memleak.redeploy.requestPathQuery>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>tomcat</id>
+ <properties>
+ <memleak.jvm.maxheap>42m</memleak.jvm.maxheap>
+ <!-- on Tomcat, we can rely on the log record which is detected bellow by maven-enforcer-plugin -->
+ <memleak.redeploy.count>1</memleak.redeploy.count>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-threadlocals-left-cleaned</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <phase>${phase.redeployment.post-integration-test}</phase>
+ <configuration>
+ <!-- assure that Tomcat ThreadLocal memory leak detection messages weren't included in the Tomcat output.
+ If so, ThreadLocals aren't kept clean and that's what users do not like (see JERSEY-2890). -->
+ <rules>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.PatternNotMatchedInFileRule">
+ <file>${external.container.logFile}</file>
+ <pattern>
+ <![CDATA[.*SEVERE.*The web application.*created a ThreadLocal with key.*avoid a probable memory leak.*]]></pattern>
+ <maxMatchedLines>3</maxMatchedLines>
+ </rule>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ <profile>
+ <id>memleak-reproducer</id>
+ <properties>
+ <hk2.version>2.5.0-b30</hk2.version>
+ </properties>
+ </profile>
+ </profiles>
+
+ <build>
+
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-locator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-utils</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingService.java b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingService.java
new file mode 100644
index 0000000..9dc4237
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingService.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.nojersey;
+
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Contract
+public interface GreetingService {
+ String getGreeting();
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingWrapper.java b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingWrapper.java
new file mode 100644
index 0000000..c4d0c9b
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/GreetingWrapper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.nojersey;
+
+import org.glassfish.hk2.api.ServiceLocator;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class GreetingWrapper {
+ GreetingService service;
+
+ public GreetingWrapper(ServiceLocator locator) {
+ service = locator.getService(GreetingService.class);
+ }
+
+ public String getInjectedGreeting() {
+ return service.getGreeting();
+ }
+
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/HelloServiceImpl.java b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/HelloServiceImpl.java
new file mode 100644
index 0000000..64aa2bf
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/HelloServiceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.nojersey;
+
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Service
+public class HelloServiceImpl implements GreetingService {
+ @Override
+ public String getGreeting() {
+ return "Hello from MyService";
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/Main.java b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/Main.java
new file mode 100644
index 0000000..d58b4c6
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/Main.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.nojersey;
+
+import org.glassfish.hk2.api.DynamicConfiguration;
+import org.glassfish.hk2.api.DynamicConfigurationService;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.api.ServiceLocatorFactory;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class Main {
+
+ public static void main(String[] args) {
+ ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
+ ServiceLocator locator = factory.create("myLocator");
+
+ DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+ DynamicConfiguration dc = dcs.createDynamicConfiguration();
+
+ AbstractBinder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(HelloServiceImpl.class).to(GreetingService.class);
+ }
+ };
+
+ locator.inject(binder);
+ binder.bind(dc);
+
+ dc.commit();
+
+ GreetingWrapper wrapper = new GreetingWrapper(locator);
+ System.out.println("result: " + wrapper.getInjectedGreeting());
+
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/MyServlet.java b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/MyServlet.java
new file mode 100644
index 0000000..2d6a266
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/java/org/glassfish/jersey/tests/memleaks/nojersey/MyServlet.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.nojersey;
+
+import org.glassfish.hk2.api.DynamicConfiguration;
+import org.glassfish.hk2.api.DynamicConfigurationService;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.api.ServiceLocatorFactory;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class MyServlet extends HttpServlet {
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
+ ServiceLocator locator = factory.create("myLocator");
+
+ DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+ DynamicConfiguration dc = dcs.createDynamicConfiguration();
+
+ AbstractBinder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(HelloServiceImpl.class).to(GreetingService.class);
+ }
+ };
+
+ binder.bind(dc);
+
+ dc.commit();
+
+ GreetingWrapper wrapper = new GreetingWrapper(locator);
+ response.getWriter().write("Greeting: " + wrapper.getInjectedGreeting());
+ locator.shutdown();
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..e0625b6
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>MyServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.tests.memleaks.nojersey.MyServlet</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.glassfish.jersey.tests.memleaks.nojersey</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>MyServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/index.jsp b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/index.jsp
new file mode 100644
index 0000000..5779d9d
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/src/main/webapp/index.jsp
@@ -0,0 +1,25 @@
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+<html>
+<body>
+ <h2>Jersey RESTful Web Application!</h2>
+ <p><a href="webapi/myresource">Jersey resource</a>
+ <p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
+ for more information on Jersey!
+</body>
+</html>
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
new file mode 100644
index 0000000..79188df
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>redeployment-threadlocals-app</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-redeployment-threadlocals-app</name>
+
+ <description>
+
+ This project shows that not careful use of ThreadLocal in a thread-pool environment is a risk. In this case, memory leaks
+ may occur under certain circumstances.
+
+ Known cases when memory leaks do happen:
+
+ [1] Tomcat with deployment by using its admin REST API (copying to webapps dir does not cause a memory leak since the
+ initialization of the application is done by a different thread, which might get eventually discarded.)
+
+ [2] Glassfish - probably works due to a fact, that HK2 is not used (as opposed to redeployment-no-jersey-test-app) and the
+ classes that participate on strong references to a GC root are loaded by webapp classloader.
+
+
+ To run this test threadlocals classloader memory leak example, execute from jersey root dir:
+
+ [1] Glassfish: mvn clean install -pl :redeployment-threadlocals-app -P gf4,memleak-leaking-test,memleak-redeployment
+
+ [2] Weblogic: mvn clean install -pl :redeployment-threadlocals-app -P wls,memleak-leaking-test,memleak-redeployment
+
+ [3] Tomcat: mvn clean install -pl :redeployment-threadlocals-app -P tomcat,memleak-leaking-test,memleak-redeployment
+
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>128m</memleak.jvm.maxheap>
+ <external.container.contextRoot>hello</external.container.contextRoot>
+
+ <memleak.redeploy.count>10000</memleak.redeploy.count>
+ <memleak.redeploy.expectedStatus>200</memleak.redeploy.expectedStatus>
+ <memleak.redeploy.requestPathQuery>${external.container.contextRoot}</memleak.redeploy.requestPathQuery>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>tomcat</id>
+ <properties>
+ <memleak.jvm.maxheap>48m</memleak.jvm.maxheap>
+ </properties>
+ </profile>
+ <profile>
+ <id>memleak-leaking-test</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-out-of-memory-did-not-occur</id>
+ <phase>${phase.redeployment.post-integration-test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/SomeClass.java b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/SomeClass.java
new file mode 100644
index 0000000..7f36e53
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/SomeClass.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.threadlocal;
+
+/**
+ * A simple class that participates in the class/object reference circle that causes a memory leak.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class SomeClass {
+
+ public static String hello() {
+ return "hello";
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/StaticReferenceClass.java b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/StaticReferenceClass.java
new file mode 100644
index 0000000..3662e79
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/StaticReferenceClass.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.threadlocal;
+
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+/**
+ * This class is a key to the classloader memory leak since it has a static reference to an object which will refer a {@link
+ * ThreadLocal} instance which refers a class object.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class StaticReferenceClass {
+
+ static final ConcurrentLinkedDeque<ThreadLocal<Class>> STATIC_HOLDER = new ConcurrentLinkedDeque<>();
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/ThreadLocalMemoryLeakServlet.java b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/ThreadLocalMemoryLeakServlet.java
new file mode 100644
index 0000000..a55c85a
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/java/org/glassfish/jersey/tests/memleaks/threadlocal/ThreadLocalMemoryLeakServlet.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.threadlocal;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * A servlet that introduces a memory leak with a single call. All the classes loaded by current classloader won't get GCed even
+ * after this application is undeployed.
+ * <p/>
+ * This servlet demonstrates that fix HK2-247 when {@link ThreadLocal} reference is changed from a static to an instance, it does
+ * not always solve memory leak issues as long as a static reference (in this case {@link StaticReferenceClass#STATIC_HOLDER})
+ * holds (even transitively) the {@link ThreadLocal} instance.
+ * <p/>
+ * To revert this case to the simple one (the original one), change the {@link #threadLocal} instance should be static and than no
+ * {@link StaticReferenceClass#STATIC_HOLDER} is needed. The memory leak occurs without any other special actions.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class ThreadLocalMemoryLeakServlet extends HttpServlet {
+
+ /**
+ * This {@link ThreadLocal} reference is held by instance reference and might be GCed; however, the class {@link SomeClass}
+ * has a reference to its classloader which has a reference to {@link StaticReferenceClass} class which has a static reference
+ * to this instance. As a result, this {@link ThreadLocal} instance is never GCed in a thread pool environment.
+ * <p/>
+ * If this field was changed to a static reference, the memory leak would occur even without the {@link
+ * StaticReferenceClass#STATIC_HOLDER} holding this instance (see {@link #doGet(HttpServletRequest, HttpServletResponse)}
+ * method bellow).
+ */
+ final ThreadLocal<Class> threadLocal = new ThreadLocal<Class>() {
+ @Override
+ protected Class initialValue() {
+ return SomeClass.class;
+ }
+ };
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ StaticReferenceClass.STATIC_HOLDER.add(threadLocal);
+ response.getWriter().write("Greeting: " + SomeClass.hello() + "\n");
+ response.getWriter().write("Thread Locals Content: " + threadLocal.get().getCanonicalName() + "\n");
+ response.getWriter().write("Holder size: " + StaticReferenceClass.STATIC_HOLDER.size());
+ }
+}
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3734180
--- /dev/null
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <servlet>
+ <servlet-name>MyServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.tests.memleaks.threadlocal.ThreadLocalMemoryLeakServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>MyServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/pom.xml b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
new file mode 100644
index 0000000..306ee22
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>bean-param-leak</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-testcase-bean-param-leak</name>
+
+ <description>
+ Reproducer of JERSEY-2800
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>96m</memleak.jvm.maxheap>
+
+ <memleak.wls.maxheap>128m</memleak.wls.maxheap>
+ <memleak.tomcat.maxheap>42m</memleak.tomcat.maxheap>
+ <memleak.jetty.maxheap>70m</memleak.jetty.maxheap>
+
+ <memleak.test.timeout>200000</memleak.test.timeout>
+
+ <memleak.wls.packagingExcludes.weblogic.xml>WEB-INF/weblogic.xml</memleak.wls.packagingExcludes.weblogic.xml>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <packagingExcludes>${memleak.wls.packagingExcludes.weblogic.xml}</packagingExcludes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>memleak-reproducer</id>
+ <properties>
+ <memleak.jersey.version>2.16</memleak.jersey.version>
+ <memleak.wls.packagingExcludes.weblogic.xml />
+ </properties>
+ </profile>
+ <profile>
+ <id>memleak-override-libraries</id>
+ <properties>
+ <memleak.wls.packagingExcludes.weblogic.xml />
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResource.java b/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResource.java
new file mode 100644
index 0000000..b78f64c
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResource.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.beanparam;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Request;
+
+import javax.inject.Singleton;
+
+/**
+ * This resource reproduces JERSEY-2800 when {@link #invokeBeanParamInject()} called repetitively.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/beanparam")
+public class BeanParamLeakResource {
+
+ public static class ParameterBean {
+ @Context
+ Request request;
+
+ @QueryParam("q")
+ String q;
+ }
+
+ @BeanParam
+ ParameterBean bean;
+
+ @POST
+ @Path("invoke")
+ public String invokeBeanParamInject() {
+ return bean.q;
+ }
+
+ @GET
+ @Path("helloworld")
+ @Produces("text/plain")
+ public String helloWorld() {
+ return "HELLO WORLD!";
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/TestApplication.java b/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/TestApplication.java
new file mode 100644
index 0000000..5333c45
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/src/main/java/org/glassfish/jersey/tests/memleaks/beanparam/TestApplication.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.beanparam;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS Application that serves {@link BeanParamLeakResource} class.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(BeanParamLeakResource.class);
+ }
+}
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..0b31bdb
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true" >
+
+ <filter>
+ <filter-name>jersey</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.memleaks.beanparam.TestApplication</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/weblogic.xml b/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/weblogic.xml
new file mode 100644
index 0000000..473e71d
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/src/main/webapp/WEB-INF/weblogic.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
+
+ <wls:container-descriptor>
+ <wls:prefer-application-packages>
+ <!-- jsr311 -->
+ <wls:package-name>javax.ws.rs.*</wls:package-name>
+ <!-- javassist -->
+ <wls:package-name>javassist.*</wls:package-name>
+ <!-- aop repackaged -->
+ <wls:package-name>org.aopalliance.*</wls:package-name>
+
+ <!-- jersey 2 -->
+ <wls:package-name>jersey.repackaged.*</wls:package-name>
+ <wls:package-name>org.glassfish.jersey.*</wls:package-name>
+ <wls:package-name>com.sun.research.ws.wadl.*</wls:package-name>
+
+ <!-- hk2 -->
+ <wls:package-name>org.glassfish.hk2.*</wls:package-name>
+ <wls:package-name>org.jvnet.hk2.*</wls:package-name>
+ <wls:package-name>org.jvnet.tiger_types.*</wls:package-name>
+ </wls:prefer-application-packages>
+
+ <wls:prefer-application-resources>
+ <wls:resource-name>META-INF/services/javax.servlet.ServletContainerInitializer</wls:resource-name>
+ <wls:resource-name>META-INF/services/javax.ws.rs.ext.RuntimeDelegate</wls:resource-name>
+
+ <!-- jersey -->
+ <wls:resource-name>META-INF/services/org.glassfish.jersey.*</wls:resource-name>
+ <wls:resource-name>org.glassfish.jersey.*</wls:resource-name>
+ <wls:resource-name>jersey.repackaged.*</wls:resource-name>
+
+ <!-- hk2 -->
+ <wls:resource-name>META-INF/services/org.glassfish.hk2.*</wls:resource-name>
+ </wls:prefer-application-resources>
+ </wls:container-descriptor>
+
+</wls:weblogic-web-app>
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/src/test/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResourceITCase.java b/tests/mem-leaks/test-cases/bean-param-leak/src/test/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResourceITCase.java
new file mode 100644
index 0000000..b9ffb16
--- /dev/null
+++ b/tests/mem-leaks/test-cases/bean-param-leak/src/test/java/org/glassfish/jersey/tests/memleaks/beanparam/BeanParamLeakResourceITCase.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.beanparam;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.memleak.common.AbstractMemoryLeakWebAppTest;
+import org.glassfish.jersey.test.memleak.common.MemoryLeakSucceedingTimeout;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * This is an integration test that reproduces JERSEY-2800 by calling RESTful resource {@link BeanParamLeakResource}
+ * repetitively.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class BeanParamLeakResourceITCase extends AbstractMemoryLeakWebAppTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Rule
+ public Timeout globalTimeout = new MemoryLeakSucceedingTimeout(300_000);
+
+ @Test
+ public void testTheLeakResourceOnce() {
+ final Response response = target("beanparam/invoke").queryParam("q", "hello").request().post(null);
+ Assert.assertEquals(200, response.getStatus());
+ assertEquals("hello", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testTheLeakEndless() {
+
+ for (long i = 0;; i++) {
+ System.out.print("\rRequests made: " + i);
+
+ final Response response = target("beanparam/invoke").queryParam("q", i).request().post(null);
+ if (response.getStatus() != 200) {
+ fail("The server was unable to fulfill the request! This may indicate that OutOfMemory exception occurred.");
+ }
+ assertEquals(Long.toString(i), response.readEntity(String.class));
+
+ }
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/pom.xml b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
new file mode 100644
index 0000000..7b7f76d
--- /dev/null
+++ b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>leaking-test-app</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-testcase-leaking-test-app</name>
+
+ <description>
+ The purpose of this test application is to test the test infrastructure whether memory leaks are correctly detected and
+ reported.
+
+ This module should not be included in the standard regression test suite since this application intentionally causes memory
+ leaks.
+
+ In order to include test of this module profile 'memleak-leaking-test' must to be enabled.
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>256m</memleak.jvm.maxheap>
+ <memleak.test.timeout>40000</memleak.test.timeout>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>memleak-leaking-test</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResource.java b/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResource.java
new file mode 100644
index 0000000..4bce46e
--- /dev/null
+++ b/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResource.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.testleak;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+
+import javax.inject.Singleton;
+
+/**
+ * Resource that causes {@link OutOfMemoryError} exception upon repetitive call of {@link #invoke(int)}.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/")
+@Singleton
+public class MemoryLeakingResource {
+
+ final List<Object> leakingList = new LinkedList<>();
+
+ @POST
+ @Path("invoke")
+ public String invoke(@DefaultValue("1048576") @QueryParam("size") int size) {
+ byte[] bytes = new byte[size];
+ leakingList.add(bytes);
+
+ return String.valueOf(leakingList.size());
+ }
+
+ @GET
+ @Path("hello")
+ @Produces("text/plain")
+ public String helloWorld() {
+ System.out.println("HELLO WORLD!");
+ return "HELLO WORLD!";
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java b/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java
new file mode 100644
index 0000000..b0435e5
--- /dev/null
+++ b/tests/mem-leaks/test-cases/leaking-test-app/src/main/java/org/glassfish/jersey/tests/memleaks/testleak/TestApplication.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.testleak;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(MemoryLeakingResource.class);
+ }
+}
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/test-cases/leaking-test-app/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7f90c9a
--- /dev/null
+++ b/tests/mem-leaks/test-cases/leaking-test-app/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true" >
+
+ <filter>
+ <filter-name>jersey</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.memleaks.testleak.TestApplication</param-value>
+ </init-param>
+ </filter>
+
+
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/src/test/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResourceITCase.java b/tests/mem-leaks/test-cases/leaking-test-app/src/test/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResourceITCase.java
new file mode 100644
index 0000000..3b7b9ab
--- /dev/null
+++ b/tests/mem-leaks/test-cases/leaking-test-app/src/test/java/org/glassfish/jersey/tests/memleaks/testleak/MemoryLeakingResourceITCase.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.testleak;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.memleak.common.AbstractMemoryLeakWebAppTest;
+import org.glassfish.jersey.test.memleak.common.MemoryLeakSucceedingTimeout;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+import static org.junit.Assert.fail;
+
+/**
+ * Performs the test of a memory leaking RESTful resource.
+ * <p/>
+ * This test class should be used to test the memory leaking test infrastructure.
+ */
+public class MemoryLeakingResourceITCase extends AbstractMemoryLeakWebAppTest {
+
+ @Rule
+ public Timeout globalTimeout = new MemoryLeakSucceedingTimeout(100_000);
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ /**
+ * This test runs i single request; as such, it may or may not cause a memory leak (and end with a failure).
+ */
+ @Test
+ public void testTheLeak() {
+
+ final WebTarget webTarget = target("invoke").queryParam("size", 1024 * 1024);
+ System.out.println(webTarget.getUri());
+ final Response response = webTarget.request().post(null);
+ Assert.assertEquals(200, response.getStatus());
+ }
+
+ /**
+ * This test should fail after certain period of time (depending on the JVM settings too).
+ */
+ @Test
+ public void testTheLeakEndless() {
+
+ while (true) {
+ System.out.print(".");
+ final Response response = target("invoke").queryParam("size", 1024 * 1024).request().post(null);
+
+ if (response.getStatus() != 200) {
+ fail("The server was unable to fulfill the request! This may indicate that OutOfMemory exception occurred.");
+ }
+ }
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/pom.xml b/tests/mem-leaks/test-cases/pom.xml
new file mode 100644
index 0000000..c7fce61
--- /dev/null
+++ b/tests/mem-leaks/test-cases/pom.xml
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-memleak-testcase</name>
+
+ <description>
+ Memory leaks test cases.
+
+ Tests in this maven submodule can be either:
+
+ [1] Simple tests executed by maven-surefire-plugin in a dedicated JVM. These tests should attempt to cause a memory leak
+ directly. The heap can be configured by means of 'memleak.jvm.maxheap' property. It can be combined with other
+ infrastructure which is described bellow.
+
+ [2] Integration tests executed by maven-surefire-plugin. These tests should test against Jersey application deployed to a
+ servlet container. The state of the servlet container (e.g., whether OutOfMemoryError occurred) should be inspected by
+ infrastructure described bellow.
+
+ TEST INFRASTRUCTURE
+
+ The test infrastructure is configured from Maven and the tests should be executed by Maven. Normally, test-cases shall
+ override maven properties defined in this pom and declare required maven plugins in their build section. All the maven
+ plugin executions will be configured from this pom.
+
+ [a] Container Runners (org.glassfish.jersey.test-framework.maven:container-runner-maven-plugin) feature Weblogic and
+ Glassfish4 with functionality: download, start, deploy and stop.
+
+ [b] Maven Enforce Custom Rules (org.glassfish.jersey.test-framework.maven:custom-enforcer-rules) that can enforce
+ non-existent Java Heap dumps files in a certain path or no OutOfMemoryError errors in a log file.
+
+ [c] Jetty execution in a dedicated JVM with configured to dump heap on OutOfMemoryError errors.
+
+ [d] Common Memleak JUnit test infrastructure that provides means to stop a test after a certain period of time and mark
+ the test as successful as well as to perform heap dumps from the Java code or to inspect log files for OutOfMemoryError
+ errors.
+
+ EXAMPLE OF EXECUTION
+
+ (executes all memleak test cases)
+ mvn clean install -amd -pl tests/mem-leaks -P gf4,memleak-test-cases -fae
+
+ (executes shutdown hook leak single test case)
+ mvn clean install -am -pl tests/mem-leaks/test-cases/shutdown-hook-leak -P gf4,memleak-test-cases -fae
+ </description>
+
+ <modules>
+ <module>bean-param-leak</module>
+ <module>shutdown-hook-leak</module>
+ <module>shutdown-hook-leak-client</module>
+ <module>leaking-test-app</module>
+ </modules>
+
+ <properties>
+ <memleak.test.timeout>300000</memleak.test.timeout>
+ <memleak.jetty.maxheap>${memleak.jvm.maxheap}</memleak.jetty.maxheap>
+
+ <!-- by default, bound to 'none' phase; if 'memleak-test-cases' profile active, they're activated -->
+ <phase.common.pre-integration-test>${phase.tests.pre-integration-test}</phase.common.pre-integration-test>
+ <phase.common.post-integration-test>${phase.tests.post-integration-test}</phase.common.post-integration-test>
+
+ <phase.tests.pre-integration-test.jetty>${phase.tests.pre-integration-test}</phase.tests.pre-integration-test.jetty>
+ <phase.tests.post-integration-test.jetty>${phase.tests.post-integration-test}</phase.tests.post-integration-test.jetty>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <jersey.config.test.memleak.timeout>${memleak.test.timeout}</jersey.config.test.memleak.timeout>
+ <jersey.config.test.container.factory>${external.container.factory}
+ </jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${external.container.port}</jersey.config.test.container.port>
+ <jersey.config.test.container.contextRoot>${external.container.contextRoot}
+ </jersey.config.test.container.contextRoot>
+ <jersey.config.test.container.logfile>${external.container.logFile}
+ </jersey.config.test.container.logfile>
+ </systemPropertyVariables>
+ </configuration>
+ <executions>
+ <execution>
+ <!-- the 'default' id is bound to 'none' because it's not possible to split the goals and re-bind them
+ while keeping the 'default' id -->
+ <id>default</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>re-bound-integration-test</id>
+ <goals>
+ <goal>integration-test</goal>
+ </goals>
+ <phase>${phase.tests.integration-test}</phase>
+ </execution>
+ <execution>
+ <id>re-bound-verify</id>
+ <goals>
+ <goal>verify</goal>
+ </goals>
+ <phase>${phase.tests.verify}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <jersey.config.test.memleak.timeout>${memleak.test.timeout}</jersey.config.test.memleak.timeout>
+ <jersey.config.test.memleak.heapDumpPath>${project.build.directory}
+ </jersey.config.test.memleak.heapDumpPath>
+ <jersey.config.test.container.factory>${external.container.factory}
+ </jersey.config.test.container.factory>
+ <jersey.config.test.container.port>${external.container.port}</jersey.config.test.container.port>
+ <jersey.config.test.container.contextRoot>${external.container.contextRoot}
+ </jersey.config.test.container.contextRoot>
+ </systemPropertyVariables>
+ <argLine>-Xmx${memleak.jvm.maxheap} -XX:+HeapDumpOnOutOfMemoryError
+ -XX:HeapDumpPath=${memleak.jvm.heapdumpdir} -XX:GCTimeLimit=20 -XX:GCHeapFreeLimit=30
+ </argLine>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-test</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <phase>${phase.tests.test}</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>memleak-test-cases</id>
+ <properties>
+ <!-- set all the phases for this sub-module tree so that the executions are un-bound from the 'none' phase -->
+ <phase.tests.test>test</phase.tests.test>
+ <phase.tests.pre-integration-test>pre-integration-test</phase.tests.pre-integration-test>
+ <phase.tests.integration-test>integration-test</phase.tests.integration-test>
+ <phase.tests.post-integration-test>post-integration-test</phase.tests.post-integration-test>
+ <phase.tests.verify>verify</phase.tests.verify>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <configuration>
+ <skip>${skip.tests}</skip>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ <stopPort>9999</stopPort>
+ <stopKey>STOP</stopKey>
+ <contextPath>/${external.container.contextRoot}</contextPath>
+ <jvmArgs>-Xms64m -Xmx${memleak.jetty.maxheap} -XX:PermSize=128m -XX:MaxPermSize=256m
+ -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${memleak.jvm.heapdumpdir}
+ -Djetty.port=${external.container.port} -Djersey.config.test.memleak.jetty.magicRunnerIdentifier
+ -Dorg.slf4j.simpleLogger.logFile=${external.container.logFile}
+ </jvmArgs>
+ <waitForChild>false</waitForChild>
+ </configuration>
+ <executions>
+ <execution>
+ <id>start-jetty</id>
+ <phase>${phase.tests.pre-integration-test.jetty}</phase>
+ <goals>
+ <goal>run-forked</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>stop-jetty</id>
+ <phase>${phase.tests.post-integration-test.jetty}</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>custom-enforcer-rules</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>enforce-out-of-memory-did-not-occur</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <phase>${phase.tests.post-integration-test}</phase>
+ <configuration>
+ <rules>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.FilePatternDoesNotExistRule">
+ <files>
+ <file>${memleak.jvm.heapdumpdir}/java_pid*.hprof</file>
+ </files>
+ </rule>
+ <rule implementation="org.glassfish.jersey.test.maven.rule.PatternNotMatchedInFileRule">
+ <file>${external.container.logFile}</file>
+ <pattern>.*java\.lang\.OutOfMemoryError.*</pattern>
+ </rule>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
+ <profile>
+ <id>gf4</id>
+ <properties>
+ <phase.tests.pre-integration-test.jetty>none</phase.tests.pre-integration-test.jetty>
+ <phase.tests.post-integration-test.jetty>none</phase.tests.post-integration-test.jetty>
+ </properties>
+ </profile>
+ <profile>
+ <id>wls</id>
+ <properties>
+ <phase.tests.pre-integration-test.jetty>none</phase.tests.pre-integration-test.jetty>
+ <phase.tests.post-integration-test.jetty>none</phase.tests.post-integration-test.jetty>
+ </properties>
+ </profile>
+ <profile>
+ <id>tomcat</id>
+ <properties>
+ <phase.tests.pre-integration-test.jetty>none</phase.tests.pre-integration-test.jetty>
+ <phase.tests.post-integration-test.jetty>none</phase.tests.post-integration-test.jetty>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
new file mode 100644
index 0000000..b554b06
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>shutdown-hook-leak-client</artifactId>
+ <name>jersey-tests-memleak-testcase-shutdown-hook-leak-client</name>
+
+ <description>
+ This web project reproduces tickets: JERSEY-2688 JERSEY-2786
+ </description>
+
+ <properties>
+ <memleak.jvm.maxheap>128m</memleak.jvm.maxheap>
+ <memleak.test.timeout>30000</memleak.test.timeout>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>memleak-reproducer</id>
+ <properties>
+ <memleak.jersey.version>2.17</memleak.jersey.version>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownleak/client/EndlessShutdownHookLeakTest.java b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownleak/client/EndlessShutdownHookLeakTest.java
new file mode 100644
index 0000000..330b76e
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownleak/client/EndlessShutdownHookLeakTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.shutdownleak.client;
+
+import java.util.logging.Logger;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation.Builder;
+import javax.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.test.memleak.common.AbstractMemoryLeakSimpleTest;
+import org.glassfish.jersey.test.memleak.common.MemoryLeakSucceedingTimeout;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+
+/**
+ * Reproducer for JERSEY-2786.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class EndlessShutdownHookLeakTest extends AbstractMemoryLeakSimpleTest {
+
+ private static final Logger LOGGER = Logger.getLogger(EndlessShutdownHookLeakTest.class.getName());
+
+ @Rule
+ public Timeout globalTimeout = new MemoryLeakSucceedingTimeout();
+
+ final Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target("http://example.com");
+
+ public EndlessShutdownHookLeakTest() {
+ LOGGER.fine("Preparing...");
+ for (int i = 0; i < 1000; ++i) {
+ shutdownHookLeakIteration();
+ }
+ }
+
+ @Test
+ public void testShutdownHookDoesNotLeak() throws Exception {
+ while (true) {
+ shutdownHookLeakIteration();
+ }
+ }
+
+ private void shutdownHookLeakIteration() {
+ System.out.print(".");
+ WebTarget target2 = target.property("Washington", "Irving");
+ Builder req = target2.request().property("how", "now");
+ req.buildGet().property("Irving", "Washington");
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
new file mode 100644
index 0000000..24386bc
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>shutdown-hook-leak</artifactId>
+ <packaging>war</packaging>
+ <name>jersey-tests-memleak-testcase-shutdown-hook-leak</name>
+
+ <properties>
+ <memleak.jvm.maxheap>128m</memleak.jvm.maxheap>
+ <memleak.tomcat.maxheap>128m</memleak.tomcat.maxheap>
+ <memleak.test.timeout>120000</memleak.test.timeout>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>memleak-test-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.glassfish.jersey.test-framework.maven</groupId>
+ <artifactId>container-runner-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>memleak-reproducer</id>
+ <properties>
+ <memleak.jersey.version>2.15</memleak.jersey.version>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ClientShutdownLeakResource.java b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ClientShutdownLeakResource.java
new file mode 100644
index 0000000..ff2a8db
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ClientShutdownLeakResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.shutdownhook;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+
+import javax.inject.Singleton;
+
+/**
+ * This resource reproduces JERSEY-2786 when {@link #invokeClient()} called repetitively.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("client")
+@Singleton
+public class ClientShutdownLeakResource {
+
+ final Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target("http://example.com");
+
+ @POST
+ @Path("invoke")
+ public String invokeClient() {
+
+ WebTarget target2 = target.property("Washington", "Irving");
+ Invocation.Builder req = target2.request().property("how", "now");
+ req.buildGet().property("Irving", "Washington");
+
+ return target.toString();
+
+ }
+
+ @GET
+ @Path("helloworld")
+ @Produces("text/plain")
+ public String helloWorld() {
+ return "HELLO WORLD!";
+ }
+
+}
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/TestApplication.java b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/TestApplication.java
new file mode 100644
index 0000000..44ddb33
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/java/org/glassfish/jersey/tests/memleaks/shutdownhook/TestApplication.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.shutdownhook;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class TestApplication extends ResourceConfig {
+
+ public TestApplication() {
+ register(ClientShutdownLeakResource.class);
+ }
+}
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/webapp/WEB-INF/web.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b36a8d0
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true" >
+
+ <filter>
+ <filter-name>jersey</filter-name>
+ <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.memleaks.shutdownhook.TestApplication</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>jersey</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+</web-app>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ShutdownLeakResourceITCase.java b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ShutdownLeakResourceITCase.java
new file mode 100644
index 0000000..6d5554f
--- /dev/null
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/src/test/java/org/glassfish/jersey/tests/memleaks/shutdownhook/ShutdownLeakResourceITCase.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.memleaks.shutdownhook;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.memleak.common.AbstractMemoryLeakWebAppTest;
+import org.glassfish.jersey.test.memleak.common.MemoryLeakSucceedingTimeout;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+import static org.junit.Assert.fail;
+
+/**
+ * This is an integration test that reproduces JERSEY-2786 by calling RESTful resource {@link ClientShutdownLeakResource}
+ * repetitively.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class ShutdownLeakResourceITCase extends AbstractMemoryLeakWebAppTest {
+
+ @Override
+ protected Application configure() {
+ return new TestApplication();
+ }
+
+ @Rule
+ public Timeout globalTimeout = new MemoryLeakSucceedingTimeout(20_000);
+
+ @Test
+ public void testTheLeakResourceOnce() {
+ final Response response = target("client/invoke").request().post(null);
+ Assert.assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testTheLeakEndless() {
+
+ while (true) {
+ System.out.print(".");
+ final Response response = target("client/invoke").request().post(null);
+
+ if (response.getStatus() != 200) {
+ fail("The server was unable to fulfill the request! This may indicate that OutOfMemory exception occurred.");
+ }
+ }
+ }
+
+}
diff --git a/tests/osgi/functional/pom.xml b/tests/osgi/functional/pom.xml
new file mode 100644
index 0000000..2eb1ba4
--- /dev/null
+++ b/tests/osgi/functional/pom.xml
@@ -0,0 +1,417 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.osgi</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-tests-osgi-functional</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-osgi-functional</name>
+ <description>
+ Functional Jersey OSGi tests
+ </description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>process-test-resources</phase>
+ <goals>
+ <goal>testResources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ <executions>
+ <execution>
+ <id>test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- use pax exam maven plugin -->
+ <plugin>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>maven-paxexam-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-config</id>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit4</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-container-forked</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit-extender-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.framework</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-link-mvn</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ <version>1.6.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.grizzly</groupId>
+ <artifactId>grizzly-http-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- dependecies for OSGi test with Apache connector -->
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.logging</groupId>
+ <artifactId>pax-logging-api</artifactId>
+ <scope>test</scope>
+ <version>1.8.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore-osgi</artifactId>
+ <scope>test</scope>
+ <version>4.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient-osgi</artifactId>
+ <scope>test</scope>
+ <version>${httpclient.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson1</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jettison</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-bean-validation</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-entity-filtering</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext</groupId>
+ <artifactId>jersey-proxy-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.bundles</groupId>
+ <artifactId>jaxrs-ri</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>servlet-api-2.5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml</groupId>
+ <artifactId>classmate</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>javax.el-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish</groupId>
+ <artifactId>javax.json</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish</groupId>
+ <artifactId>jsonp-jaxrs</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2.external</groupId>
+ <artifactId>aopalliance-repackaged</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-base</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-jaxrs</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.6.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>testsSkipJdk6</id>
+ <activation>
+ <jdk>1.6</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/PackageScanningTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/AbstractJsonOsgiIntegrationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/AbstractJsonOsgiIntegrationTest.java
new file mode 100644
index 0000000..7d3a5dc
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/AbstractJsonOsgiIntegrationTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Abstract JSON OSGi integration test.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public abstract class AbstractJsonOsgiIntegrationTest {
+
+ private static final String CONTEXT = "/jersey";
+ private static final URI baseUri = UriBuilder.fromUri("http://localhost").port(Helper.getPort()).path(CONTEXT).build();
+
+ protected abstract Feature getJsonProviderFeature();
+
+ @Test
+ public void testJson() throws Exception {
+ final Feature jsonProviderFeature = getJsonProviderFeature();
+ final Client client = ClientBuilder.newClient();
+ final ResourceConfig resourceConfig = new ResourceConfig(JsonResource.class);
+
+ if (jsonProviderFeature != null) {
+ client.register(jsonProviderFeature);
+ resourceConfig.register(jsonProviderFeature);
+ }
+
+ HttpServer server = null;
+ try {
+ server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ final String result = client.target(baseUri).path("/json").request(MediaType.APPLICATION_JSON).get(String.class);
+
+ System.out.println("RESULT = " + result);
+ assertThat(result, containsString("Jim"));
+ } finally {
+ if (server != null) {
+ server.shutdownNow();
+ }
+ }
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ApacheOsgiIntegrationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ApacheOsgiIntegrationTest.java
new file mode 100644
index 0000000..77e376e
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ApacheOsgiIntegrationTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@RunWith(PaxExam.class)
+public class ApacheOsgiIntegrationTest {
+
+ private static final URI baseUri = UriBuilder.fromUri("http://localhost").port(Helper.getPort()).path("/jersey").build();
+
+ @Configuration
+ public static Option[] configuration() {
+ final List<Option> options = Helper.getCommonOsgiOptions();
+ options.addAll(Helper.expandedList(
+ mavenBundle().groupId("org.ops4j.pax.logging").artifactId("pax-logging-api").versionAsInProject(),
+ mavenBundle().groupId("org.apache.httpcomponents").artifactId("httpcore-osgi").versionAsInProject(),
+ mavenBundle().groupId("org.apache.httpcomponents").artifactId("httpclient-osgi").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.connectors").artifactId("jersey-apache-connector")
+ .versionAsInProject()
+
+ ));
+ return Helper.asArray(options);
+ }
+
+ @Path("/apacheOsgiTest")
+ public static class ApacheOsgiTestResource {
+
+ @GET
+ public String getMe() {
+ return "OK";
+ }
+ }
+
+ @Test
+ public void testSimpleResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(ApacheOsgiTestResource.class);
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ final ClientConfig clientConfig = new ClientConfig();
+ clientConfig.connectorProvider(new ApacheConnectorProvider());
+ final Client c = ClientBuilder.newClient(clientConfig);
+
+ final Response response = c.target(baseUri).path("/apacheOsgiTest").request().buildGet().invoke();
+
+ final String result = response.readEntity(String.class);
+ assertEquals("OK", result);
+ server.shutdownNow();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BasicOsgiIntegrationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BasicOsgiIntegrationTest.java
new file mode 100644
index 0000000..104347f
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BasicOsgiIntegrationTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class BasicOsgiIntegrationTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+ return Helper.asArray(options);
+ }
+
+ @Path("/super-simple")
+ public static class SuperSimpleResource {
+
+ @GET
+ public String getMe() {
+ return "OK";
+ }
+ }
+
+ @Test
+ public void testSimpleResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(SuperSimpleResource.class);
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ Client c = ClientBuilder.newClient();
+ final Response response = c.target(baseUri).path("/super-simple").request().buildGet().invoke();
+
+ String result = response.readEntity(String.class);
+ System.out.println("RESULT = " + result);
+
+ assertEquals("OK", result);
+
+ server.shutdownNow();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationResource.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationResource.java
new file mode 100644
index 0000000..f67d8d4
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationResource.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("bean-validation")
+public class BeanValidationResource {
+
+ @POST
+ public String post(@NotNull @FormParam("formParam") final String formParam) {
+ return formParam;
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
new file mode 100644
index 0000000..fc8076a
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.validation.ValidationFeature;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * Basic test of Bean Validation.
+ *
+ * @author Michal Gajdos
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@RunWith(PaxExam.class)
+public class BeanValidationTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder.fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // for debug purposes
+ // PaxRunnerOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ // validation
+ mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-bean-validation").versionAsInProject(),
+ mavenBundle().groupId("org.hibernate").artifactId("hibernate-validator").versionAsInProject(),
+ mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
+ mavenBundle().groupId("javax.el").artifactId("javax.el-api").versionAsInProject()
+ ));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Test
+ public void testBeanValidationResourceFeature() throws Exception {
+ _test(400, true, false);
+ }
+
+ @Test
+ public void testBeanValidationResourceAutoDiscovery() throws Exception {
+ _test(400, false, false);
+ }
+
+ @Test
+ public void testBeanValidationResourceManualRegistration() throws Exception {
+ _test(400, true, true);
+ }
+
+ @Test
+ public void testBeanValidationResourceNoValidationFeature() throws Exception {
+ // Even though properties are disabled BV is registered.
+ _test(400, false, true);
+ }
+
+ protected void _test(final int expectedResponseCode,
+ final boolean registerFeature,
+ final boolean disableMetainfServicesLookup) {
+ final ResourceConfig resourceConfig = new ResourceConfig(BeanValidationResource.class);
+ if (registerFeature) {
+ resourceConfig.register(ValidationFeature.class);
+ }
+ if (disableMetainfServicesLookup) {
+ resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, Boolean.TRUE);
+
+ resourceConfig.register(org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainerProvider.class);
+ }
+
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ final Form form = new Form();
+ final String formValue = "formValue";
+ form.asMap().add("formParam", formValue);
+
+ final Client client = ClientBuilder.newClient();
+ final String entity = client.target(baseUri)
+ .path("/bean-validation")
+ .request()
+ .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
+
+ assertEquals(formValue, entity);
+
+ final Response response = client.target(baseUri)
+ .path("/bean-validation")
+ .request()
+ .post(Entity.entity(new Form(), MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+
+ assertEquals(expectedResponseCode, response.getStatus());
+
+ server.shutdownNow();
+ }
+
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JaxRsRiBundleTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JaxRsRiBundleTest.java
new file mode 100644
index 0000000..34c9977
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JaxRsRiBundleTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * Basic test of JAX-RS RI bundle.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class JaxRsRiBundleTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions(false);
+
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ mavenBundle().groupId("org.glassfish.jersey.bundles").artifactId("jaxrs-ri").versionAsInProject(),
+
+ mavenBundle().groupId("org.mortbay.jetty").artifactId("servlet-api-2.5").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.grizzly").artifactId("grizzly-http-servlet").versionAsInProject()
+ ));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Test
+ public void testSimpleResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(SimpleResource.class);
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ final Client client = ClientBuilder.newClient();
+ final String response = client.target(baseUri).path("/simple").request().get(String.class);
+
+ System.out.println("RESULT = " + response);
+ assertEquals("OK", response);
+
+ server.shutdownNow();
+ }
+
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJackson1Test.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJackson1Test.java
new file mode 100644
index 0000000..8552fc1
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJackson1Test.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+
+import org.glassfish.jersey.jackson1.Jackson1Feature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JsonJackson1Test extends AbstractJsonOsgiIntegrationTest {
+
+ @Configuration
+ public static Option[] configuration() {
+ final List<Option> options = new ArrayList<>();
+
+ options.addAll(Helper.getCommonOsgiOptions());
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-json-jackson1").versionAsInProject(),
+
+ // jersey-json dependencies
+ mavenBundle().groupId("org.codehaus.jackson").artifactId("jackson-core-asl").versionAsInProject(),
+ mavenBundle().groupId("org.codehaus.jackson").artifactId("jackson-mapper-asl").versionAsInProject(),
+ mavenBundle().groupId("org.codehaus.jackson").artifactId("jackson-jaxrs").versionAsInProject(),
+ mavenBundle().groupId("org.codehaus.jackson").artifactId("jackson-xc").versionAsInProject()
+ ));
+
+ return Helper.asArray(options);
+ }
+
+ @Override
+ protected Feature getJsonProviderFeature() {
+ return new Jackson1Feature();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
new file mode 100644
index 0000000..644d053
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JsonJacksonTest extends AbstractJsonOsgiIntegrationTest {
+
+ @Configuration
+ public static Option[] configuration() {
+ final List<Option> options = new ArrayList<>();
+
+ options.addAll(Helper.getCommonOsgiOptions());
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-json-jackson").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-entity-filtering").versionAsInProject(),
+
+ // jersey-json dependencies
+ mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-core").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-databind").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-annotations").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml.jackson.jaxrs").artifactId("jackson-jaxrs-base").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml.jackson.jaxrs").artifactId("jackson-jaxrs-json-provider")
+ .versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml.jackson.module").artifactId("jackson-module-jaxb-annotations")
+ .versionAsInProject()
+ ));
+
+ return Helper.asArray(options);
+ }
+
+ @Override
+ protected Feature getJsonProviderFeature() {
+ return new JacksonFeature();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJettisonTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJettisonTest.java
new file mode 100644
index 0000000..afa5cc0
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJettisonTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.Configuration;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JsonJettisonTest extends AbstractJsonOsgiIntegrationTest {
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = new ArrayList<Option>();
+
+ options.addAll(Helper.getCommonOsgiOptions());
+ options.addAll(Helper.expandedList(
+ // jersey-json dependencies
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-json-jettison").versionAsInProject(),
+ mavenBundle().groupId("org.codehaus.jettison").artifactId("jettison").versionAsInProject()
+ ));
+
+ return Helper.asArray(options);
+ }
+
+ @Override
+ protected Feature getJsonProviderFeature() {
+ return new JettisonFeature();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
new file mode 100644
index 0000000..d8bc1f0
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+
+import org.eclipse.persistence.jaxb.BeanValidationMode;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackage;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JsonMoxyTest extends AbstractJsonOsgiIntegrationTest {
+
+ @Configuration
+ public static Option[] configuration() {
+ final List<Option> options = new ArrayList<>();
+
+ options.addAll(Helper.getCommonOsgiOptions());
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ bootDelegationPackage("javax.xml.bind"),
+ bootDelegationPackage("javax.xml.bind.*"),
+ // validation
+ bootDelegationPackage("javax.xml.parsers"),
+ bootDelegationPackage("javax.xml.parsers.*"),
+
+ // moxy dependencies
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-moxy").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-entity-filtering").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.moxy").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.core").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.asm").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish").artifactId("javax.json").versionAsInProject(),
+
+ // validation
+ mavenBundle().groupId("org.hibernate").artifactId("hibernate-validator").versionAsInProject(),
+ mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
+ mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
+ mavenBundle().groupId("javax.el").artifactId("javax.el-api").versionAsInProject()
+ ));
+
+ return Helper.asArray(options);
+ }
+
+ @Override
+ protected Feature getJsonProviderFeature() {
+ // Turn off BV otherwise the test is not stable.
+ return new Feature() {
+
+ @Override
+ public boolean configure(final FeatureContext context) {
+ context.register(new MoxyJsonConfig()
+ .property(MarshallerProperties.BEAN_VALIDATION_MODE, BeanValidationMode.NONE)
+ .resolver());
+
+ return true;
+ }
+ };
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonProcessingTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonProcessingTest.java
new file mode 100644
index 0000000..6ab4c56
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonProcessingTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * Basic test of Json Processing.
+ *
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class JsonProcessingTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ // JSON processing.
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-json-processing")
+ .versionAsInProject(),
+ mavenBundle().groupId("org.glassfish").artifactId("javax.json").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish").artifactId("jsonp-jaxrs").versionAsInProject()
+ ));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Path("/")
+ public static class Resource {
+
+ @POST
+ public JsonObject postJsonObject(final JsonObject jsonObject) {
+ return jsonObject;
+ }
+ }
+
+ @Test
+ public void testJsonObject() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(Resource.class);
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+ final JsonObject jsonObject = Json.createObjectBuilder().add("foo", "bar").build();
+
+ final Client client = ClientBuilder.newClient();
+ final JsonObject entity = client
+ .target(baseUri)
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.json(jsonObject), JsonObject.class);
+
+ System.out.println("RESULT = " + entity);
+ assertEquals(jsonObject, entity);
+
+ server.shutdownNow();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonResource.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonResource.java
new file mode 100644
index 0000000..f9c3bdd
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("json")
+public class JsonResource {
+
+ @XmlRootElement
+ public static class NameBean {
+
+ public String name = "Harrison";
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public NameBean getBean() {
+ NameBean result = new NameBean();
+ result.name = "Jim";
+
+ return result;
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/MultiPartTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/MultiPartTest.java
new file mode 100644
index 0000000..3b17ca0
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/MultiPartTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.media.multipart.BodyPart;
+import org.glassfish.jersey.media.multipart.BodyPartEntity;
+import org.glassfish.jersey.media.multipart.MultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class MultiPartTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // jersey-multipart dependencies
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-multipart").versionAsInProject(),
+ mavenBundle().groupId("org.jvnet.mimepull").artifactId("mimepull").versionAsInProject()));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Path("/multipart-simple")
+ public static class MultiPartResource {
+
+ @GET
+ @Produces("multipart/mixed")
+ public Response one() {
+ MultiPart entity = new MultiPart();
+ BodyPart part = new BodyPart("This is the only segment", new MediaType("text", "plain"));
+ entity.getBodyParts().add(part);
+ return Response.ok(entity).type("multipart/mixed").build();
+ }
+
+ }
+
+ @Test
+ public void testMultiPartResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(MultiPartResource.class).register(new MultiPartFeature());
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ Client c = ClientBuilder.newClient(new ClientConfig().register(MultiPartFeature.class));
+ final Response response = c.target(baseUri).path("/multipart-simple").request().buildGet().invoke();
+
+ MultiPart result = response.readEntity(MultiPart.class);
+ System.out.println("RESULT = " + result);
+
+ checkEntity("This is the only segment", (BodyPartEntity) result.getBodyParts().get(0).getEntity());
+
+ server.shutdownNow();
+ }
+
+ private void checkEntity(String expected, BodyPartEntity entity) throws IOException {
+ // Convert the raw bytes into a String
+ InputStreamReader sr = new InputStreamReader(entity.getInputStream());
+ StringWriter sw = new StringWriter();
+ while (true) {
+ int ch = sr.read();
+ if (ch < 0) {
+ break;
+ }
+ sw.append((char) ch);
+ }
+ // Perform the comparison
+ assertEquals(expected, sw.toString());
+ }
+
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java
new file mode 100644
index 0000000..48480b2
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.grizzly2.servlet.GrizzlyWebContainerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.servlet.ServletContainer;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * NOTE: This test is excluded on JDK6 as it requires Servlet 3.1 API that is built against JDK 7.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class PackageScanningTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-sse").versionAsInProject(),
+
+ mavenBundle().groupId("javax.servlet").artifactId("javax.servlet-api").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.grizzly").artifactId("grizzly-http-servlet").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.containers").artifactId("jersey-container-servlet-core")
+ .versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.containers").artifactId("jersey-container-grizzly2-servlet")
+ .versionAsInProject(),
+
+ // MBR/MBW for JSON-P is on the classpath.
+ mavenBundle().groupId("org.glassfish").artifactId("javax.json").versionAsInProject()
+ ));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Test
+ public void testSimpleResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig().packages(SimpleResource.class.getPackage().getName());
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ _testScannedResources(server);
+ }
+
+ @Test
+ public void testSimpleResourceInitParameters() throws Exception {
+ Map<String, String> initParams = new HashMap<String, String>();
+ initParams.put(
+ ServerProperties.PROVIDER_PACKAGES,
+ SimpleResource.class.getPackage().getName());
+
+ // TODO - temporary workaround
+ // This is a workaround related to issue JERSEY-2093; grizzly (1.9.5) needs to have the correct context
+ // classloader set
+ ClassLoader myClassLoader = getClass().getClassLoader();
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ HttpServer server = null;
+ try {
+ Thread.currentThread().setContextClassLoader(myClassLoader);
+ server = GrizzlyWebContainerFactory.create(baseUri, ServletContainer.class, initParams);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ // END of workaround - when grizzly updated to more recent version, only the inner line of try clause should remain:
+
+ _testScannedResources(server);
+ }
+
+ private void _testScannedResources(final HttpServer server) throws Exception {
+ final Client client = ClientBuilder.newClient();
+
+ assertEquals("OK", client.target(baseUri).path("/simple").request().get(String.class));
+ // resources in subpackages aren't supported yet because the osgi recursive scanning is set to false
+// assertEquals("sub-OK", client.target(baseUri).path("/sub-packaged").request().get(String.class));
+
+ server.shutdownNow();
+ }
+
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ResourceBundleTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ResourceBundleTest.java
new file mode 100644
index 0000000..7f6c6fb
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/ResourceBundleTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.io.ByteArrayOutputStream;
+import java.net.URI;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogManager;
+import java.util.logging.SimpleFormatter;
+import java.util.logging.StreamHandler;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.internal.Errors;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+/**
+ * Ensures server localization resource bundle gets loaded fine in OSGi runtime.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(PaxExam.class)
+public class ResourceBundleTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+ options.addAll(Helper.expandedList(
+ // PaxRunnerOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")
+ ));
+
+ return Helper.asArray(options);
+ }
+
+ @Path("/non-deployable")
+ public static class BadResource {
+
+ @GET
+ private String getMe() {
+ return "no way";
+ }
+ }
+
+ @Test
+ public void testBadResource() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(BadResource.class);
+
+ ByteArrayOutputStream logOutput = new ByteArrayOutputStream();
+ Handler logHandler = new StreamHandler(logOutput, new SimpleFormatter());
+
+ GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig, false);
+
+ // TODO: there should be a better way to get the log output!
+ final Enumeration<String> loggerNames = LogManager.getLogManager().getLoggerNames();
+ while (loggerNames.hasMoreElements()) {
+ String name = loggerNames.nextElement();
+ if (name.startsWith("org.glassfish")) {
+ LogManager.getLogManager().getLogger(Errors.class.getName()).addHandler(logHandler);
+ }
+ }
+ GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig, false);
+ logOutput.flush();
+ final String logOutputAsString = logOutput.toString();
+
+ Assert.assertFalse(logOutputAsString.contains("[failed to localize]"));
+ Assert.assertTrue(logOutputAsString.contains("BadResource"));
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SimpleResource.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SimpleResource.java
new file mode 100644
index 0000000..6b672cb
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SimpleResource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/simple")
+public class SimpleResource {
+
+ @GET
+ public String getMe() {
+ return "OK";
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SseTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SseTest.java
new file mode 100644
index 0000000..c558f32
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/SseTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.UriBuilder;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.BundleContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * Basic test for SSE module OSGification.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@RunWith(PaxExam.class)
+public class SseTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Inject
+ protected BundleContext bundleContext;
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // Jersey SSE dependencies
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-sse").versionAsInProject()));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @Path("/sse")
+ public static class SseResource {
+
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput getIt() throws IOException {
+ final EventOutput result = new EventOutput();
+ result.write(new OutboundEvent.Builder().name("event1").data(String.class, "ping").build());
+ result.write(new OutboundEvent.Builder().name("event2").data(String.class, "pong").build());
+ result.close();
+ return result;
+ }
+ }
+
+ @Test
+ public void testSse() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(SseResource.class, SseFeature.class);
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+
+ Client c = ClientBuilder.newClient();
+ c.register(SseFeature.class);
+
+ final List<String> data = new LinkedList<String>();
+ final CountDownLatch latch = new CountDownLatch(2);
+
+ final EventSource eventSource = new EventSource(c.target(baseUri).path("/sse")) {
+
+ @Override
+ public void onEvent(InboundEvent event) {
+ try {
+ data.add(event.readData());
+ latch.countDown();
+ } catch (ProcessingException e) {
+ // ignore
+ }
+ }
+ };
+
+ assertTrue(latch.await(2, TimeUnit.SECONDS));
+
+ eventSource.close();
+ assertEquals(2, data.size());
+
+ server.shutdownNow();
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/WebResourceFactoryTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/WebResourceFactoryTest.java
new file mode 100644
index 0000000..3f99393
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/WebResourceFactoryTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.proxy.WebResourceFactory;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.osgi.test.util.Helper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+
+/**
+ * @author Michal Gajdos
+ */
+@RunWith(PaxExam.class)
+public class WebResourceFactoryTest {
+
+ private static final String CONTEXT = "/jersey";
+
+ private static final URI baseUri = UriBuilder
+ .fromUri("http://localhost")
+ .port(Helper.getPort())
+ .path(CONTEXT).build();
+
+ @Configuration
+ public static Option[] configuration() {
+ List<Option> options = Helper.getCommonOsgiOptions();
+
+ options.addAll(Helper.expandedList(
+ // jersey-multipart dependencies
+ mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-proxy-client").versionAsInProject()));
+
+ options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
+ return Helper.asArray(options);
+ }
+
+ @XmlRootElement
+ public static class MyBean {
+ public String name;
+ }
+
+ @Path("myresource")
+ public static interface MyResourceIfc {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ String getIt();
+
+ @POST
+ @Consumes({MediaType.APPLICATION_XML})
+ @Produces({MediaType.APPLICATION_XML})
+ List<MyBean> postIt(List<MyBean> entity);
+
+ @Path("{id}")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ String getId(@PathParam("id") String id);
+
+ @Path("query")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ String getByName(@QueryParam("name") String name);
+
+ @Path("subresource")
+ MySubResourceIfc getSubResource();
+ }
+
+ public static class MyResource implements MyResourceIfc {
+
+ @Override
+ public String getIt() {
+ return "Got it!";
+ }
+
+ @Override
+ public List<MyBean> postIt(List<MyBean> entity) {
+ return entity;
+ }
+
+ @Override
+ public String getId(String id) {
+ return id;
+ }
+
+ @Override
+ public String getByName(String name) {
+ return name;
+ }
+
+ @Override
+ public MySubResourceIfc getSubResource() {
+ return new MySubResource();
+ }
+ }
+
+ public static class MySubResource implements MySubResourceIfc {
+
+ @Override
+ public MyBean getMyBean() {
+ MyBean bean = new MyBean();
+ bean.name = "Got it!";
+ return bean;
+ }
+ }
+
+ public static interface MySubResourceIfc {
+
+ @GET
+ @Produces(MediaType.APPLICATION_XML)
+ public MyBean getMyBean();
+ }
+
+ private HttpServer server;
+ private MyResourceIfc resource;
+
+ @Before
+ public void setUp() throws Exception {
+ final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
+ server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
+ resource = WebResourceFactory.newResource(MyResourceIfc.class, ClientBuilder.newClient().target(baseUri));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ server.shutdownNow();
+ }
+
+ @Test
+ public void testGetIt() {
+ assertEquals("Got it!", resource.getIt());
+ }
+
+ @Test
+ public void testPostIt() {
+ MyBean bean = new MyBean();
+ bean.name = "Foo";
+ assertEquals("Foo", resource.postIt(Collections.singletonList(bean)).get(0).name);
+ }
+
+ @Test
+ public void testPathParam() {
+ assertEquals("Bar", resource.getId("Bar"));
+ }
+
+ @Test
+ public void testQueryParam() {
+ assertEquals("Jersey2", resource.getByName("Jersey2"));
+ }
+
+ @Test
+ public void testSubResource() {
+ assertEquals("Got it!", resource.getSubResource().getMyBean().name);
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/subpackage/SimpleResourceSubpackaged.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/subpackage/SimpleResourceSubpackaged.java
new file mode 100644
index 0000000..e5434eb
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/subpackage/SimpleResourceSubpackaged.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.basic.subpackage;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+/**
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+@Path("/sub-packaged")
+public class SimpleResourceSubpackaged {
+ @GET
+ public String getMe() {
+ return "sub-OK";
+ }
+}
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java
new file mode 100644
index 0000000..c3d9670
--- /dev/null
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.osgi.test.util;
+
+import java.security.AccessController;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.ops4j.pax.exam.Option;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackage;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+/**
+ * Helper class to be used by individual tests.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Michal Gajdos
+ */
+public class Helper {
+
+ /**
+ * Jersey HTTP port.
+ */
+ private static final int port = getEnvVariable(TestProperties.CONTAINER_PORT, 8080);
+
+ /**
+ * Returns an integer value of given system property, or a default value
+ * as defined by the other method parameter, if the system property can
+ * not be used.
+ *
+ * @param varName name of the system variable.
+ * @param defaultValue the default value to return if the system variable is missing or can not be parsed as an integer.
+ * @return an integer value taken either from the system property or the default value as defined by the defaultValue parameter.
+ */
+ public static int getEnvVariable(final String varName, int defaultValue) {
+ if (null == varName) {
+ return defaultValue;
+ }
+ String varValue = AccessController.doPrivileged(PropertiesHelper.getSystemProperty(varName));
+ if (null != varValue) {
+ try {
+ return Integer.parseInt(varValue);
+ } catch (NumberFormatException e) {
+ // will return default value below
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Returns a value of {@value TestProperties#CONTAINER_PORT} property which should be used as port number for test container.
+ *
+ * @return port number.
+ */
+ public static int getPort() {
+ return port;
+ }
+
+ /**
+ * Adds a system property for Maven local repository location to the PaxExam OSGi runtime if a "localRepository" property
+ * is present in the map of the system properties.
+ *
+ * @param options list of options to add the local repository property to.
+ * @return list of options enhanced by the local repository property if this property is set or the given list if the
+ * previous condition is not met.
+ */
+ public static List<Option> addPaxExamMavenLocalRepositoryProperty(List<Option> options) {
+ final String localRepository = AccessController.doPrivileged(PropertiesHelper.getSystemProperty("localRepository"));
+
+ if (localRepository != null) {
+ options.addAll(expandedList(systemProperty("org.ops4j.pax.url.mvn.localRepository").value(localRepository)));
+ }
+
+ return options;
+ }
+
+ /**
+ * Convert list of OSGi options to an array.
+ *
+ * @param options list of OSGi options.
+ * @return array of OSGi options.
+ */
+ public static Option[] asArray(final List<Option> options) {
+ return options.toArray(new Option[options.size()]);
+ }
+
+ /**
+ * Create new list of common OSGi integration test options.
+ *
+ * @return list of common OSGi integration test options.
+ */
+ public static List<Option> getCommonOsgiOptions() {
+ return getCommonOsgiOptions(true);
+ }
+
+ /**
+ * Create new list of common OSGi integration test options.
+ *
+ * @param includeJerseyJaxRsLibs indicates whether JaxRs and Jersey bundles should be added into the resulting list of
+ * options.
+ * @return list of common OSGi integration test options.
+ */
+ public static List<Option> getCommonOsgiOptions(final boolean includeJerseyJaxRsLibs) {
+ final List<Option> options = new LinkedList<Option>(expandedList(
+ // systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("FINEST"),
+ systemProperty("org.osgi.service.http.port").value(String.valueOf(port)),
+ systemProperty(TestProperties.CONTAINER_PORT).value(String.valueOf(port)),
+ systemProperty("org.osgi.framework.system.packages.extra").value("javax.annotation"),
+
+ // javax.annotation has to go first!
+ mavenBundle().groupId("javax.annotation").artifactId("javax.annotation-api").versionAsInProject(),
+
+ junitBundles(),
+
+ // HK2
+ mavenBundle().groupId("org.glassfish.hk2").artifactId("hk2-api").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.hk2").artifactId("osgi-resource-locator").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.hk2").artifactId("hk2-locator").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.hk2").artifactId("hk2-utils").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.hk2.external").artifactId("javax.inject").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.hk2.external").artifactId("aopalliance-repackaged").versionAsInProject(),
+ mavenBundle().groupId("org.javassist").artifactId("javassist").versionAsInProject(),
+
+ // Grizzly
+ systemPackage("sun.misc"),
+ mavenBundle().groupId("org.glassfish.grizzly").artifactId("grizzly-framework").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.grizzly").artifactId("grizzly-http").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.grizzly").artifactId("grizzly-http-server").versionAsInProject(),
+
+ // javax.validation
+ mavenBundle().groupId("javax.validation").artifactId("validation-api").versionAsInProject(),
+
+ // Jersey Grizzly
+ mavenBundle().groupId("org.glassfish.jersey.containers").artifactId("jersey-container-grizzly2-http")
+ .versionAsInProject()
+ ));
+
+ if (includeJerseyJaxRsLibs) {
+ options.addAll(expandedList(
+ // JAX-RS API
+ mavenBundle().groupId("javax.ws.rs").artifactId("javax.ws.rs-api").versionAsInProject(),
+
+ // Jersey bundles
+ mavenBundle().groupId("org.glassfish.jersey.core").artifactId("jersey-common").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-jaxb").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.core").artifactId("jersey-server").versionAsInProject(),
+ mavenBundle().groupId("org.glassfish.jersey.core").artifactId("jersey-client").versionAsInProject(),
+
+ // Jersey Injection provider
+ mavenBundle().groupId("org.glassfish.jersey.inject").artifactId("jersey-hk2").versionAsInProject()
+ ));
+ }
+
+ return addPaxExamMavenLocalRepositoryProperty(options);
+ }
+
+ /**
+ * Create expanded options list from the supplied options.
+ *
+ * @param options options to be expanded into the option list.
+ * @return expanded options list.
+ */
+ public static List<Option> expandedList(Option... options) {
+ return Arrays.asList(options(options));
+ }
+}
diff --git a/tests/osgi/functional/src/test/resources/log4j.properties b/tests/osgi/functional/src/test/resources/log4j.properties
new file mode 100644
index 0000000..13d56f8
--- /dev/null
+++ b/tests/osgi/functional/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+log4j.rootCategory=ERROR, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout.ConversionPattern=[%30.30c{1}] - %m%n
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
diff --git a/tests/osgi/pom.xml b/tests/osgi/pom.xml
new file mode 100644
index 0000000..e55fc8a
--- /dev/null
+++ b/tests/osgi/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.osgi</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-osgi</name>
+
+ <description>
+ Test modules containing test scenario types that cover OSGi.
+ </description>
+
+ <modules>
+ <module>functional</module>
+ </modules>
+</project>
diff --git a/tests/performance/benchmarks/README.md b/tests/performance/benchmarks/README.md
new file mode 100644
index 0000000..6616896
--- /dev/null
+++ b/tests/performance/benchmarks/README.md
@@ -0,0 +1,29 @@
+[//]: # " Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+
+## How to run?
+
+To run all benchmarks execute:
+
+`mvn clean install exec:exec` or `mvn clean install && java -jar target/benchmarks.jar`
+
+To run specific benchmark, e.g. `JacksonBenchmark`:
+
+`mvn clean install && java -cp target/benchmarks.jar org.glassfish.jersey.tests.performance.benchmark.JacksonBenchmark`
+
+## Where to find more info/examples?
+
+JMH page: http://openjdk.java.net/projects/code-tools/jmh/
+
+JMH examples: http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
diff --git a/tests/performance/benchmarks/pom.xml b/tests/performance/benchmarks/pom.xml
new file mode 100644
index 0000000..40314a0
--- /dev/null
+++ b/tests/performance/benchmarks/pom.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>performance-test-benchmarks</artifactId>
+ <packaging>jar</packaging>
+ <name>performance-test-benchmarks</name>
+
+ <description>Micro-benchmarks to see performance of Jersey and it's features</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-generator-annprocess</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <executable>java</executable>
+ <arguments>
+ <argument>-classpath</argument>
+ <classpath />
+ <argument>org.glassfish.jersey.tests.performance.benchmark.AllBenchmarks</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <configuration>
+ <minimizeJar>false</minimizeJar>
+ </configuration>
+ <executions>
+ <execution>
+ <id>shade-archive</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <finalName>${uberjar.name}</finalName>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.glassfish.jersey.tests.performance.benchmark.AllBenchmarks</mainClass>
+ </transformer>
+ </transformers>
+ <filters>
+ <filter>
+ <!--
+ Shading signed JARs will fail without this.
+ http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
+ -->
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkMode>always</forkMode>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+
+ <properties>
+ <uberjar.name>benchmark</uberjar.name>
+ </properties>
+</project>
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/AllBenchmarks.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/AllBenchmarks.java
new file mode 100644
index 0000000..badc3ee
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/AllBenchmarks.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import java.util.concurrent.TimeUnit;
+
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+/**
+ * @author Michal Gajdos
+ */
+public class AllBenchmarks {
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(ClientBenchmark.class.getSimpleName())
+ .include(JacksonBenchmark.class.getSimpleName())
+ .include(LocatorBenchmark.class.getSimpleName())
+ .include(JerseyUriBuilderBenchmark.class.getSimpleName())
+ // Measure throughput in seconds (ops/s).
+ .mode(Mode.Throughput)
+ .timeUnit(TimeUnit.SECONDS)
+ // Warm-up setup.
+ .warmupIterations(16)
+ .warmupTime(TimeValue.milliseconds(2500))
+ // Measurement setup.
+ .measurementIterations(16)
+ .measurementTime(TimeValue.milliseconds(2500))
+ // Fork! (Invoke benchmarks in separate JVM)
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/ClientBenchmark.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/ClientBenchmark.java
new file mode 100644
index 0000000..bf55df9
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/ClientBenchmark.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.util.client.LoopBackConnectorProvider;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * Locator {@link org.glassfish.jersey.server.ApplicationHandler} benchmark.
+ *
+ * @author Michal Gajdos
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 16, time = 1, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 16, time = 1, timeUnit = TimeUnit.SECONDS)
+@Fork(1)
+@State(Scope.Benchmark)
+public class ClientBenchmark {
+
+ private volatile Client client;
+
+ @Setup
+ public void start() throws Exception {
+ client = ClientBuilder.newClient(LoopBackConnectorProvider.getClientConfig());
+ }
+
+ @TearDown
+ public void shutdown() {
+ client.close();
+ }
+
+ @Benchmark
+ public Response get() throws Exception {
+ return client.target("foo").request().get();
+ }
+
+ @Benchmark
+ public Response post() throws Exception {
+ return client.target("foo").request().post(Entity.text("bar"));
+ }
+
+ @Benchmark
+ public Response asyncBlock() throws Exception {
+ return client.target("foo").request().async().get().get();
+ }
+
+ @Benchmark
+ public Future<Response> asyncIgnore() throws Exception {
+ return client.target("foo").request().async().get(new InvocationCallback<Response>() {
+ @Override
+ public void completed(final Response response) {
+ // NOOP
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
+ // NOOP
+ }
+ });
+ }
+
+ @Benchmark
+ public Future<Response> asyncEntityIgnore() throws Exception {
+ return client.target("foo").request().async().post(Entity.text("bar"), new InvocationCallback<Response>() {
+ @Override
+ public void completed(final Response response) {
+ // NOOP
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
+ // NOOP
+ }
+ });
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(ClientBenchmark.class.getSimpleName())
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JacksonBenchmark.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JacksonBenchmark.java
new file mode 100644
index 0000000..8b527ff
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JacksonBenchmark.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import java.util.concurrent.TimeUnit;
+
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.test.util.server.ContainerRequestBuilder;
+import org.glassfish.jersey.tests.performance.benchmark.entity.json.JacksonApplication;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * Jackson Entity Filtering {@link org.glassfish.jersey.server.ApplicationHandler} benchmark.
+ *
+ * @author Michal Gajdos
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+@State(Scope.Benchmark)
+public class JacksonBenchmark {
+
+ @Param(value = {"projects/basic", "projects/detailed"})
+ private String path;
+
+ @Param(value = {"false", "true"})
+ private String filtering;
+
+ private volatile ApplicationHandler handler;
+ private volatile ContainerRequest request;
+
+ @Setup
+ public void start() throws Exception {
+ handler = new ApplicationHandler(new JacksonApplication(Boolean.valueOf(filtering)));
+ }
+
+ @Setup(Level.Iteration)
+ public void request() {
+ request = ContainerRequestBuilder
+ .from(path, "GET")
+ .build();
+ }
+
+ @TearDown
+ public void shutdown() {
+ }
+
+ @Benchmark
+ public ContainerResponse measureResource() throws Exception {
+ return handler.apply(request).get();
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(JacksonBenchmark.class.getSimpleName())
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JerseyUriBuilderBenchmark.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JerseyUriBuilderBenchmark.java
new file mode 100644
index 0000000..a02570c
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JerseyUriBuilderBenchmark.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import java.util.concurrent.TimeUnit;
+
+import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * {@link JerseyUriBuilder} benchmark for parsing templates.
+ *
+ * @author David Schlosnagle
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+@State(Scope.Benchmark)
+public class JerseyUriBuilderBenchmark {
+
+ @Param(value = {"http://localhost:8080/a/b/c", "https://localhost:443/{a}/{b}/{c:.+}"})
+ private String uriTemplate;
+
+ private volatile JerseyUriBuilder uriBuilder;
+
+ @Setup
+ public void start() throws Exception {
+ uriBuilder = new JerseyUriBuilder();
+ }
+
+ @Benchmark
+ public JerseyUriBuilder uri() throws Exception {
+ return uriBuilder.uri(uriTemplate);
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(JerseyUriBuilderBenchmark.class.getSimpleName())
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/LocatorBenchmark.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/LocatorBenchmark.java
new file mode 100644
index 0000000..e4c9da9
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/LocatorBenchmark.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.test.util.server.ContainerRequestBuilder;
+import org.glassfish.jersey.tests.performance.benchmark.server.LocatorApplication;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * Locator {@link org.glassfish.jersey.server.ApplicationHandler} benchmark.
+ *
+ * @author Michal Gajdos
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 16, time = 2500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+@State(Scope.Benchmark)
+public class LocatorBenchmark {
+
+ @Param(value = {"helloworld", "helloworld/locator"})
+ private String path;
+
+ @Param(value = {"GET", "POST", "PUT"})
+ private String method;
+
+ private volatile ApplicationHandler handler;
+ private volatile ContainerRequest request;
+
+ @Setup
+ public void start() throws Exception {
+ handler = new ApplicationHandler(new LocatorApplication());
+ }
+
+ @Setup(Level.Iteration)
+ public void request() {
+ request = ContainerRequestBuilder
+ .from(path, method)
+ .entity("GET".equals(method) ? null : "Hello World!", handler)
+ .build();
+ }
+
+ @TearDown
+ public void shutdown() {
+ }
+
+ @Benchmark
+ public Future<ContainerResponse> measure() throws Exception {
+ return handler.apply(request);
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(LocatorBenchmark.class.getSimpleName())
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/JacksonApplication.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/JacksonApplication.java
new file mode 100644
index 0000000..22ce001
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/JacksonApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JacksonApplication extends ResourceConfig {
+
+ public JacksonApplication(final boolean entityFilteringEnabled) {
+ register(ProjectsResource.class);
+
+ if (entityFilteringEnabled) {
+ register(EntityFilteringFeature.class);
+ }
+ register(JacksonFeature.class);
+
+ // Turn off Monitoring to not affect benchmarks.
+ property(ServerProperties.MONITORING_ENABLED, false);
+ property(ServerProperties.MONITORING_STATISTICS_ENABLED, false);
+ property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, false);
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Project.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Project.java
new file mode 100644
index 0000000..4e33d9a
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Project.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Project entity class. Fields {@code tasks} and {@code users} are available only in detailed view (defined via
+ * {@link ProjectDetailedView}).
+ *
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"JavaDoc", "UnusedDeclaration"})
+@XmlRootElement
+public class Project {
+
+ private Long id;
+
+ private String name;
+
+ private String description;
+
+ @ProjectDetailedView
+ private List<Task> tasks;
+
+ @ProjectDetailedView
+ private List<User> users;
+
+ public Project() {
+ }
+
+ public Project(final Long id, final String name, final String description) {
+ this.id = id;
+ this.name = name;
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public List<Task> getTasks() {
+ return tasks;
+ }
+
+ public void setTasks(final List<Task> tasks) {
+ this.tasks = tasks;
+ }
+
+ public List<User> getUsers() {
+ return users;
+ }
+
+ public void setUsers(final List<User> users) {
+ this.users = users;
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectDetailedView.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectDetailedView.java
new file mode 100644
index 0000000..c40edee
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectDetailedView.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * Entity-filtering annotation used to define detailed view on returned {@link Project} entities.
+ *
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface ProjectDetailedView {
+
+ /**
+ * Factory class for creating instances of {@code ProjectDetailedView} annotation.
+ */
+ public static class Factory extends AnnotationLiteral<ProjectDetailedView> implements ProjectDetailedView {
+
+ private Factory() {
+ }
+
+ public static ProjectDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectsResource.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectsResource.java
new file mode 100644
index 0000000..2e50f4b
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/ProjectsResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Resource class for {@link Project projects}. Provides methods to retrieve projects in "default" view ({@link #getProjects()}
+ * and in "detailed" view ({@link #getDetailedProjects()}.
+ *
+ * @author Michal Gajdos
+ */
+@Path("projects")
+@Produces("application/json")
+public class ProjectsResource {
+
+ private static final List<Project> projects;
+
+ static {
+ final Project project = new Project(1L, "foo", "bar");
+ final User user = new User(1L, "foo", "foo@bar.baz");
+ final Task task = new Task(1L, "foo", "bar");
+
+ project.setUsers(Arrays.asList(user));
+ project.setTasks(Arrays.asList(task, task));
+
+ projects = Arrays.asList(project, project);
+ }
+
+ @GET
+ @Path("basic")
+ public List<Project> getProjects() {
+ return getDetailedProjects();
+ }
+
+ @GET
+ @Path("detailed")
+ @ProjectDetailedView
+ public List<Project> getDetailedProjects() {
+ return projects;
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Task.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Task.java
new file mode 100644
index 0000000..91a2f5c
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/Task.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Task entity class. Fields {@code project} and {@code user} are available only in detailed view (defined via
+ * {@link TaskDetailedView}).
+ *
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"UnusedDeclaration", "JavaDoc"})
+@XmlRootElement
+public class Task {
+
+ private Long id;
+
+ private String name;
+
+ private String description;
+
+ @TaskDetailedView
+ private Project project;
+
+ @TaskDetailedView
+ private User user;
+
+ public Task() {
+ }
+
+ public Task(final Long id, final String name, final String description) {
+ this.id = id;
+ this.name = name;
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public Project getProject() {
+ return project;
+ }
+
+ public void setProject(final Project project) {
+ this.project = project;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(final User user) {
+ this.user = user;
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/TaskDetailedView.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/TaskDetailedView.java
new file mode 100644
index 0000000..1caf023
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/TaskDetailedView.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * Entity-filtering annotation used to define detailed view on returned {@link Task} entities.
+ *
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface TaskDetailedView {
+
+ /**
+ * Factory class for creating instances of {@code TaskDetailedView} annotation.
+ */
+ public static class Factory extends AnnotationLiteral<TaskDetailedView> implements TaskDetailedView {
+
+ private Factory() {
+ }
+
+ public static TaskDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/User.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/User.java
new file mode 100644
index 0000000..3b52b22
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/User.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * User entity class. Fields {@code projects} and {@code tasks} are available only in detailed view (defined via
+ * {@link UserDetailedView} on getters).
+ *
+ * @author Michal Gajdos
+ */
+@SuppressWarnings({"UnusedDeclaration", "JavaDoc"})
+@XmlRootElement
+public class User {
+
+ private Long id;
+
+ private String name;
+
+ private String email;
+
+ private List<Project> projects;
+
+ private List<Task> tasks;
+
+ public User() {
+ }
+
+ public User(final Long id, final String name, final String email) {
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ @UserDetailedView
+ public List<Project> getProjects() {
+ return projects;
+ }
+
+ public void setProjects(final List<Project> projects) {
+ this.projects = projects;
+ }
+
+ @UserDetailedView
+ public List<Task> getTasks() {
+ return tasks;
+ }
+
+ public void setTasks(final List<Task> tasks) {
+ this.tasks = tasks;
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/UserDetailedView.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/UserDetailedView.java
new file mode 100644
index 0000000..b73fe8f
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/entity/json/UserDetailedView.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.entity.json;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+import org.glassfish.jersey.message.filtering.EntityFiltering;
+
+/**
+ * Entity-filtering annotation used to define detailed view on returned {@link User} entities.
+ *
+ * @author Michal Gajdos
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@EntityFiltering
+public @interface UserDetailedView {
+
+ /**
+ * Factory class for creating instances of {@code UserDetailedView} annotation.
+ */
+ public static class Factory extends AnnotationLiteral<UserDetailedView> implements UserDetailedView {
+
+ private Factory() {
+ }
+
+ public static UserDetailedView get() {
+ return new Factory();
+ }
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorApplication.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorApplication.java
new file mode 100644
index 0000000..4924cb7
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+/**
+ * @author Michal Gajdos
+ */
+public class LocatorApplication extends ResourceConfig {
+
+ public LocatorApplication() {
+ register(LocatorResource.class);
+
+ // Turn off Monitoring to not affect benchmarks.
+ property(ServerProperties.MONITORING_ENABLED, false);
+ property(ServerProperties.MONITORING_STATISTICS_ENABLED, false);
+ property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, false);
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorResource.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorResource.java
new file mode 100644
index 0000000..24228a9
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("resource")
+@Produces("text/plain")
+public class LocatorResource {
+
+ @GET
+ public String get() {
+ return "Hello World!";
+ }
+
+ @POST
+ public String post(final String entity) {
+ return entity;
+ }
+
+ @PUT
+ public void put(final String entity) {
+ // NOOP
+ }
+
+ @Path("locator")
+ public Class<?> locator() {
+ return LocatorResource.class;
+ }
+}
diff --git a/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/JacksonTest.java b/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/JacksonTest.java
new file mode 100644
index 0000000..b611d34
--- /dev/null
+++ b/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/JacksonTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server;
+
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.tests.performance.benchmark.entity.json.JacksonApplication;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class JacksonTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new JacksonApplication(false);
+ }
+
+ @Test
+ public void testResourceMethod() {
+ final Response response = target().path("projects/basic").request().get();
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ }
+
+ @Test
+ public void testSubResourceMethod() {
+ final Response response = target().path("projects/detailed").request().get();
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ }
+}
diff --git a/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorTest.java b/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorTest.java
new file mode 100644
index 0000000..ea70157
--- /dev/null
+++ b/tests/performance/benchmarks/src/test/java/org/glassfish/jersey/tests/performance/benchmark/server/LocatorTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Michal Gajdos
+ */
+public class LocatorTest extends JerseyTest {
+
+ @Override
+ protected ResourceConfig configure() {
+ enable(TestProperties.LOG_TRAFFIC);
+
+ return new LocatorApplication();
+ }
+
+ @Test
+ public void testResourceMethod() {
+ final Response response = target().path("resource").request("text/plain").get();
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ assertThat("Unexpected response entity.", response.readEntity(String.class), is("Hello World!"));
+ }
+
+ @Test
+ public void testSubResourceMethod() {
+ final Response response = target().path("resource").path("locator").request("text/plain").get();
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ assertThat("Unexpected response entity.", response.readEntity(String.class), is("Hello World!"));
+ }
+
+ @Test
+ public void testPost() {
+ final Response response = target().path("resource")
+ .request("text/plain")
+ .post(Entity.text("Hello World!"));
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ assertThat("Unexpected response entity.", response.readEntity(String.class), is("Hello World!"));
+ }
+
+ @Test
+ public void testPostLocator() {
+ final Response response = target().path("resource").path("locator")
+ .request("text/plain")
+ .post(Entity.text("Hello World!"));
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(200));
+ assertThat("Unexpected response entity.", response.readEntity(String.class), is("Hello World!"));
+ }
+
+ @Test
+ public void testPut() {
+ final Response response = target().path("resource")
+ .request("text/plain")
+ .put(Entity.text("Hello World!"));
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(204));
+ }
+
+ @Test
+ public void testPutLocator() {
+ final Response response = target().path("resource").path("locator")
+ .request("text/plain")
+ .put(Entity.text("Hello World!"));
+
+ assertThat("Wrong HTTP response code returned.", response.getStatus(), is(204));
+ }
+}
diff --git a/tests/performance/etc/client/json-post.lua b/tests/performance/etc/client/json-post.lua
new file mode 100644
index 0000000..1db504c
--- /dev/null
+++ b/tests/performance/etc/client/json-post.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "POST"
+io.input("json.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/json"
diff --git a/tests/performance/etc/client/json-put.lua b/tests/performance/etc/client/json-put.lua
new file mode 100644
index 0000000..a32d686
--- /dev/null
+++ b/tests/performance/etc/client/json-put.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "PUT"
+io.input("json.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/json"
diff --git a/tests/performance/etc/client/json.dat b/tests/performance/etc/client/json.dat
new file mode 100644
index 0000000..521c930
--- /dev/null
+++ b/tests/performance/etc/client/json.dat
@@ -0,0 +1 @@
+{"name":"Wolfgang","age":21,"address":"Salzburg"}
diff --git a/tests/performance/etc/client/kryo-post.lua b/tests/performance/etc/client/kryo-post.lua
new file mode 100644
index 0000000..77c4fa1
--- /dev/null
+++ b/tests/performance/etc/client/kryo-post.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "POST"
+io.input("kryo.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/x-kryo"
diff --git a/tests/performance/etc/client/kryo-put.lua b/tests/performance/etc/client/kryo-put.lua
new file mode 100644
index 0000000..39d96fa
--- /dev/null
+++ b/tests/performance/etc/client/kryo-put.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "PUT"
+io.input("kryo.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/x-kryo"
diff --git a/tests/performance/etc/client/kryo.dat b/tests/performance/etc/client/kryo.dat
new file mode 100644
index 0000000..2045bc3
--- /dev/null
+++ b/tests/performance/etc/client/kryo.dat
@@ -0,0 +1 @@
+ParióJuleó
\ No newline at end of file
diff --git a/tests/performance/etc/client/person-post.lua b/tests/performance/etc/client/person-post.lua
new file mode 100644
index 0000000..0256635
--- /dev/null
+++ b/tests/performance/etc/client/person-post.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "POST"
+io.input("person.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/person"
diff --git a/tests/performance/etc/client/person-put.lua b/tests/performance/etc/client/person-put.lua
new file mode 100644
index 0000000..9bfc4bb
--- /dev/null
+++ b/tests/performance/etc/client/person-put.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "PUT"
+io.input("person.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/person"
diff --git a/tests/performance/etc/client/person.dat b/tests/performance/etc/client/person.dat
new file mode 100644
index 0000000..fd0955b
--- /dev/null
+++ b/tests/performance/etc/client/person.dat
@@ -0,0 +1,4 @@
+name: Mozart
+age: 21
+address: Salzburg
+
diff --git a/tests/performance/etc/client/text-post.lua b/tests/performance/etc/client/text-post.lua
new file mode 100644
index 0000000..c4b6fa9
--- /dev/null
+++ b/tests/performance/etc/client/text-post.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "POST"
+io.input("text.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "text/plain"
diff --git a/tests/performance/etc/client/text-put.lua b/tests/performance/etc/client/text-put.lua
new file mode 100644
index 0000000..3f91001
--- /dev/null
+++ b/tests/performance/etc/client/text-put.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "PUT"
+io.input("text.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "text/plain"
diff --git a/tests/performance/etc/client/text.dat b/tests/performance/etc/client/text.dat
new file mode 100644
index 0000000..c743cac
--- /dev/null
+++ b/tests/performance/etc/client/text.dat
@@ -0,0 +1 @@
+Prague ( /ˈprɑːɡ/; Czech: Praha pronounced [ˈpraɦa] ( listen)) is the capital and largest city of the Czech Republic. It is the fourteenth-largest city in the European Union.[5] It is also the historical capital of Bohemia proper. Situated in the north-west of the country on the Vltava river, the city is home to about 1.3 million people, while its larger urban zone is estimated to have a population of nearly 2 million.[3] The city has a temperate oceanic climate, with warm summers and chilly winters.
diff --git a/tests/performance/etc/client/xml-post.lua b/tests/performance/etc/client/xml-post.lua
new file mode 100644
index 0000000..f365ee9
--- /dev/null
+++ b/tests/performance/etc/client/xml-post.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "POST"
+io.input("xml.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/xml"
diff --git a/tests/performance/etc/client/xml-put.lua b/tests/performance/etc/client/xml-put.lua
new file mode 100644
index 0000000..7aa11c9
--- /dev/null
+++ b/tests/performance/etc/client/xml-put.lua
@@ -0,0 +1,21 @@
+--[[
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+--]]
+wrk.method = "PUT"
+io.input("xml.dat")
+wrk.body = io.read("*all")
+wrk.headers["Content-Type"] = "application/xml"
diff --git a/tests/performance/etc/client/xml.dat b/tests/performance/etc/client/xml.dat
new file mode 100644
index 0000000..22624a1
--- /dev/null
+++ b/tests/performance/etc/client/xml.dat
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><name>Wolfgang</name><age>21</age><address>Salzburg</address></person>
diff --git a/tests/performance/etc/data/MEASUREMENT_DATA b/tests/performance/etc/data/MEASUREMENT_DATA
new file mode 100644
index 0000000..e728638
--- /dev/null
+++ b/tests/performance/etc/data/MEASUREMENT_DATA
@@ -0,0 +1,79 @@
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+#
+# File format:
+# application directory name|command line to generate load on client machines|JMX URI for the application|MBean name|output filename
+#
+
+mbw-text-plain|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.text.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-text-get.properties
+mbw-text-plain|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.text.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-text-put.properties
+mbw-text-plain|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.text.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-text-post.properties
+
+mbw-json-moxy|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-moxy-get.properties
+mbw-json-moxy|wrk -c64 -t16 -d800s -s json-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-moxy-put.properties
+mbw-json-moxy|wrk -c64 -t16 -d800s -s json-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-moxy-post.properties
+
+mbw-json-jackson|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-jackson-get.properties
+mbw-json-jackson|wrk -c64 -t16 -d800s -s json-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-jackson-put.properties
+mbw-json-jackson|wrk -c64 -t16 -d800s -s json-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-json-jackson-post.properties
+
+mbw-kryo|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.kryo.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-kryo-get.properties
+mbw-kryo|wrk -c64 -t16 -d800s -s kryo-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.kryo.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-kryo-put.properties
+mbw-kryo|wrk -c64 -t16 -d800s -s kryo-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.kryo.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-kryo-post.properties
+
+mbw-xml-moxy|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-moxy-get.properties
+mbw-xml-moxy|wrk -c64 -t16 -d800s -s xml-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-moxy-post.properties
+mbw-xml-moxy|wrk -c64 -t16 -d800s -s xml-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-moxy-put.properties
+
+mbw-xml-jaxb|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-jaxb-get.properties
+mbw-xml-jaxb|wrk -c64 -t16 -d800s -s xml-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-jaxb-post.properties
+mbw-xml-jaxb|wrk -c64 -t16 -d800s -s xml-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-xml-jaxb-put.properties
+
+mbw-custom-provider|wrk -c64 -t16 -d800s -s person-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.custom.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-custom-post.properties
+mbw-custom-provider|wrk -c64 -t16 -d800s -s person-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.custom.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-custom-put.properties
+mbw-custom-provider|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.mbw.custom.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|mbw-custom-get.properties
+
+param-srl|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/srl/jednaBedna\;m=bedna\?q=jedna|org.glassfish.jersey.tests.performance.param.srl.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|param-srl-get.properties
+param-srl|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/srm/jednaBedna\;m=bedna\?q=jedna|org.glassfish.jersey.tests.performance.param.srl.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|param-srm-get.properties
+
+filter-global|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-global-get.properties
+filter-global|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-global-put.properties
+filter-global|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-global-post.properties
+
+filter-name|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-name-post.properties
+filter-name|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-name-put.properties
+filter-name|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-name-get.properties
+
+filter-dynamic|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-dynamic-post.properties
+filter-dynamic|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-dynamic-put.properties
+filter-dynamic|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.filter.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|filter-dynamic-get.properties
+
+interceptor-global|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-global-post.properties
+interceptor-global|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-global-put.properties
+interceptor-global|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.global.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-global-get.properties
+
+interceptor-name|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-name-post.properties
+interceptor-name|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-name-put.properties
+interceptor-name|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.name.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-name-get.properties
+
+interceptor-dynamic|wrk -c64 -t16 -d800s -s text-post.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-dynamic-post.properties
+interceptor-dynamic|wrk -c64 -t16 -d800s -s text-put.lua http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-dynamic-put.properties
+interceptor-dynamic|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/|org.glassfish.jersey.tests.performance.interceptor.dynamic.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|interceptor-dynamic-get.properties
+
+proxy-injection|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/method-injected/without-parameters|org.glassfish.jersey.tests.performance.proxy.injection.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|proxy-injection-raw-gets.properties
+proxy-injection|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/method-injected/all-parameters|org.glassfish.jersey.tests.performance.proxy.injection.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|proxy-injection-method-params.properties
+proxy-injection|wrk -c64 -t16 -d800s http://SERVER_MACHINE:SERVER_PORT/APP_CONTEXT/field-injected/without-parameters|org.glassfish.jersey.tests.performance.proxy.injection.JaxRsApplication||metrics:name=org.glassfish.jersey.server.ApplicationHandler.handle|proxy-injection-field-params.properties
diff --git a/tests/performance/etc/hudson/jersey-performance-test-common.sh b/tests/performance/etc/hudson/jersey-performance-test-common.sh
new file mode 100644
index 0000000..da4f8c1
--- /dev/null
+++ b/tests/performance/etc/hudson/jersey-performance-test-common.sh
@@ -0,0 +1,264 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+APP_LIST=(mbw-text-plain \
+ mbw-json-moxy mbw-json-jackson \
+ mbw-xml-moxy mbw-xml-jaxb \
+ mbw-custom-provider \
+ mbw-kryo \
+ param-srl \
+ filter-global filter-name filter-dynamic \
+ interceptor-global interceptor-name interceptor-dynamic \
+ proxy-injection)
+
+WARM_UP_SECONDS=300
+WAIT_FOR_APP_STARTUP_SEC=5
+WAIT_FOR_APP_RUNNING_SEC=60
+CHECK_RUNNER_INTERVAL=5
+CHECK_TERM_INTERVAL=10
+
+JMX_URI_TEMPLATE="service:jmx:rmi:///jndi/rmi://SERVER_MACHINE:11112/jmxrmi"
+SAMPLES=30
+
+#uncomment for debug purposes:
+#WARM_UP_SECONDS=3
+#WAIT_FOR_APP_STARTUP_SEC=2
+#WAIT_FOR_APP_RUNNING_SEC=1
+#CHECK_RUNNER_INTERVAL=1
+#CHECK_TERM_INTERVAL=2
+#SAMPLES=3
+#/debug
+
+MODULES_TO_BUILD=""
+for app in ${APP_LIST[*]}; do
+ MODULES_TO_BUILD="$MODULES_TO_BUILD,tests/performance/test-cases/$app"
+done
+MODULES_TO_BUILD=`echo $MODULES_TO_BUILD|sed -e's/,//'`
+
+SERVER_LIST=()
+CLIENT_LIST_ALL=()
+
+
+function waitForGroupStatus() {
+ echo "########### Waiting for group status: $*"
+ RUNNER_ID=$1
+ shift
+ GROUP_ID=$1
+ shift
+ STATUS=$1
+
+ echo "#`date`" > $STATUS_DIR/.runner.$RUNNER_ID.waiting.$GROUP_ID.$STATUS
+ FILE="$STATUS_DIR/.group.$GROUP_ID.running.$RUNNER_ID.$STATUS"
+
+ rm -f $STATUS_DIR/.group.$GROUP_ID.running.$RUNNER_ID.*
+
+ available=false
+ while [ "$available" != true ]; do
+ if [ -e "$FILE" ]; then
+ available=true
+ else
+ sleep 1
+ fi
+ done
+}
+
+function releaseRunnerAndGroup() {
+ echo "########### Release Runner and Group: $*"
+ RUNNER_ID=$1
+ shift
+ GROUP_ID=$1
+
+ echo "#`date`" > $STATUS_DIR/.runner.$RUNNER_ID.available
+ rm -f $STATUS_DIR/.group.$GROUP_ID.running.$RUNNER_ID.* $STATUS_DIR/.runner.$RUNNER_ID.running
+}
+
+function checkWaitingRunners() {
+ echo "########### Check Waiting Runners"
+ for waiting_file in `ls $STATUS_DIR/.runner.*.waiting.*.lock 2> /dev/null`; do
+ filename_array=(`basename $waiting_file | tr "." " "`)
+
+ runner_id=${filename_array[1]}
+ group_id=${filename_array[3]}
+ status=${filename_array[4]}
+
+ _files=($STATUS_DIR/.group.$group_id.running.*)
+ if [ ! -f "${_files}" ]; then
+ echo "#`date`" > "$STATUS_DIR/.group.$group_id.running.$runner_id.lock"
+ rm $waiting_file
+ fi
+ done
+
+ for waiting_file in `ls $STATUS_DIR/.runner.*.waiting.*.open 2> /dev/null`; do
+ filename_array=(`basename $waiting_file | tr "." " "`)
+
+ runner_id=${filename_array[1]}
+ group_id=${filename_array[3]}
+ status=${filename_array[4]}
+
+ _files=($STATUS_DIR/.group.$group_id.running.*.lock)
+ if [ ! -f "${_files}" ]; then
+ echo "#`date`" > "$STATUS_DIR/.group.$group_id.running.$runner_id.open"
+ rm $waiting_file
+ fi
+ done
+}
+
+function createMachineFiles {
+ echo "########### Creating machine files in $STATUS_DIR for: $*"
+ RUNNER_ID=$1
+ shift
+ GROUP_ID=$1
+ shift
+ SERVER_MACHINE=$1
+ shift
+ CLIENT_LIST=($@)
+
+ echo ${GROUP_ID} > $STATUS_DIR/.runner.$RUNNER_ID.group
+ echo "#`date`" > $STATUS_DIR/.runner.$RUNNER_ID.available
+ echo ${SERVER_MACHINE} > $STATUS_DIR/.runner.$RUNNER_ID.server
+ echo ${CLIENT_LIST[@]} > $STATUS_DIR/.runner.$RUNNER_ID.clients
+
+ SERVER_LIST=("${SERVER_LIST[@]}" "$SERVER_MACHINE")
+ CLIENT_LIST_ALL=("${CLIENT_LIST_ALL[@]}" "${CLIENT_LIST[@]}")
+}
+
+function waitForTerminator {
+ echo "########### Waiting for finish"
+ # wait for the last round to finish
+ terminated=false
+ while [ "$terminated" != true ]; do
+ checkWaitingRunners
+ _files=($STATUS_DIR/.runner.*.running)
+ if [ ! -f "${_files}" ]; then
+ terminated=true
+ fi
+ if [ "$terminated" != true ]; then
+ echo "########### Terminated tests: $terminated, waiting $CHECK_TERM_INTERVAL sec..."
+ sleep $CHECK_TERM_INTERVAL
+ fi
+ done
+
+ echo "DONE!"
+
+ wait
+ sleep 4
+ wait
+}
+
+function testLoop {
+ # Following is the main measurement loop
+ # MEASUREMENT_DATA is the input data in the following format:
+ # application directory name|command line to generate load on client machines|JMX URI for the application|MBean name|output filename
+
+ echo "########### Let's test it, reading from $MEASUREMENT_DATA file"
+
+ TOTAL_COUNT=`cat $MEASUREMENT_DATA | grep -v "^#" | grep "^." | wc -l | sed -e 's/ *//g'`
+ INDEX=0
+ cat $MEASUREMENT_DATA | grep -v "^#" | grep "^." | while IFS="\|" read app ab_cmdline app_class agent_param mbean filename
+ do
+ INDEX=`expr $INDEX + 1`
+ echo "========================================= DATA [$INDEX/$TOTAL_COUNT] =============================================="
+ echo "app = $app"
+ echo "app_class = $app_class"
+ echo "ab_cmdline= $ab_cmdline"
+
+ spawned=false
+ while [ "$spawned" != true ]; do
+ for runner_file in `ls $STATUS_DIR/.runner.*.available 2> /dev/null`; do
+ if [ "$spawned" != true ]; then
+ filename_array=(`basename $runner_file | tr "." " "`)
+ actual_runner=${filename_array[1]}
+ echo "#`date`" > $STATUS_DIR/.runner.$actual_runner.running
+ rm $runner_file
+
+ SERVER_MACHINE=`cat $STATUS_DIR/.runner.$actual_runner.server`
+ APP_CONTEXT=$app
+ CLIENT_LIST=(`cat $STATUS_DIR/.runner.$actual_runner.clients`)
+ ab_cmdline=`echo $ab_cmdline | sed -e"s/SERVER_MACHINE/$SERVER_MACHINE/" | sed -e"s/SERVER_PORT/$SERVER_PORT/" | sed -e"s/APP_CONTEXT/$APP_CONTEXT/"`
+ JMX_URI=`echo $JMX_URI_TEMPLATE | sed -e"s/SERVER_MACHINE/$SERVER_MACHINE/"`
+ group_id=`cat $STATUS_DIR/.runner.$actual_runner.group`
+
+ echo "#[$INDEX/$TOTAL_COUNT]" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$app" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$app_class" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$ab_cmdline" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$filename" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$mbean" >> $STATUS_DIR/.runner.$actual_runner.running
+ echo "$agent_param" >> $STATUS_DIR/.runner.$actual_runner.running
+
+ spawned=true
+ singleTest &
+ fi
+ done
+ checkWaitingRunners
+ if [ "$spawned" != true ]; then
+ sleep $CHECK_RUNNER_INTERVAL
+ fi
+ done
+ done
+}
+
+function removeOldCapturedData {
+ rm -f $WORKSPACE/*.properties
+}
+
+function retrieveJmxClient {
+ echo "########### Retrieving JMX client"
+ scp jerseyrobot@${SERVER_LIST[0]}:jmxclient.jar .
+}
+
+function prepareClients {
+ echo "########### Copy client files to each client"
+ for CLIENT_MACHINE in ${CLIENT_LIST_ALL[@]}; do
+ echo "... copy client files to ${CLIENT_MACHINE}"
+ scp $WORKSPACE/jersey/tests/performance/etc/client/* jerseyrobot@${CLIENT_MACHINE}:. &
+ done
+
+ wait
+}
+
+function buildTestAppOnServers {
+ echo "########### Building test applications on each server"
+ # git fetch jersey on the server machine and build all apps there:
+ for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd $HOME/workspace/jersey && '$GIT_FETCH_COMMAND' && mvn -pl '$MODULES_TO_BUILD' -am -Dskip.tests=true clean install)' &
+ done
+
+ wait
+}
+
+function cleanupHudsonSlave {
+ rm -f $STATUS_DIR/.runner.* $STATUS_DIR/.group.*
+}
+
+function cleanupServer {
+ echo "########### Kill java processes on server $1"
+ ssh -n jerseyrobot@$1 'if ! test -e `ps h o pid -Cjava`; then kill -s TERM `ps h o pid -Cjava` ; fi'
+}
+
+function cleanupServers {
+ echo "########### Kill all java processes on each server"
+ for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ cleanupServer ${SERVER_MACHINE}
+ done
+}
+
+
+trap "cleanupHudsonSlave; cleanupServers" EXIT SIGTERM SIGINT
+
+#uncomment for debug purposes:
+#trap 'echo "[$BASH_SOURCE:$LINENO] $BASH_COMMAND" >> .debug; tail -10 .debug > .debug.swap; mv .debug.swap .debug' DEBUG
diff --git a/tests/performance/etc/hudson/jersey-performance-test-grizzly.sh b/tests/performance/etc/hudson/jersey-performance-test-grizzly.sh
new file mode 100644
index 0000000..2cf2a22
--- /dev/null
+++ b/tests/performance/etc/hudson/jersey-performance-test-grizzly.sh
@@ -0,0 +1,119 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+#
+# Environment setup:
+#
+# GIT_FETCH_COMMAND - specify GIT command to get sources to test, e.g. git checkout master && git pull
+#
+# STATUS_DIR=$HOME/.hudson-jersey3-performance-test
+# mkdir -p $STATUS_DIR
+# source jersey-performance-test-common.sh
+# test machine sets: cfg#, group, server, clients
+# createMachineFiles 1 1 server1 client1a client1b
+# createMachineFiles 1 2 server2 client2a client2b
+# MEASUREMENT_DATA=~/MEASUREMENT_DATA
+#
+
+SERVER_PORT=8080
+
+function singleTest() {
+ echo "================================================================================="
+ echo "===== SINGLE TEST RUN, SERVER=$SERVER_MACHINE, loader=$ab_cmdline, app=$app, JMX_URI=$JMX_URI, group_id=$group_id ====="
+ echo "================================================================================="
+
+ echo "########### going to start the test app $app"
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-grizzly-runner; rm -rf app; mkdir -p app; cp $HOME/workspace/jersey/tests/performance/test-cases/'$app'/target/runner/lib/* app/; JAVA_OPTIONS="-javaagent:$HOME/jersey-perftest-agent.jar" ./start.sh '$app_class' http://0.0.0.0:8080/'$app'/ 4 8)' &
+
+ waitForGroupStatus $actual_runner $group_id "open"
+
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo "########### going to start load generator at $client_machine"
+ (sleep $WAIT_FOR_APP_STARTUP_SEC; ssh -n jerseyrobot@$client_machine "nohup $ab_cmdline" & ) &
+ done
+
+ echo "########### waiting $WARM_UP_SECONDS sec to warm up server"
+ sleep $WARM_UP_SECONDS
+
+ echo "########### warm up finished, terminating ab clients..."
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo -n "########### warm up finished, going to stop load generator at $client_machine..."
+ ssh -n jerseyrobot@$client_machine 'if ! test -e `ps h o pid -Cwrk`; then kill -s INT `ps h o pid -Cwrk` ; fi'
+ echo " done."
+ done
+
+ waitForGroupStatus $actual_runner $group_id "lock"
+
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo "########### going to start load generator at $client_machine again"
+ (ssh -n jerseyrobot@$client_machine "nohup $ab_cmdline" & ) &
+ done
+
+ echo "########### waiting before start capturing jmx data"
+ sleep $WAIT_FOR_APP_RUNNING_SEC
+
+ echo "########### starting jmx client to capture data"
+ if ! java -cp jmxclient.jar org.glassfish.jersey.tests.performance.jmxclient.Main $JMX_URI "$mbean" OneMinuteRate $SAMPLES $filename; then
+ echo "########### ERROR WHEN PROCESSING LINE#${LINE_NUMBER}, test-case: ${app}, mbean: ${mbean}, filename: ${filename}!"
+ fi
+
+ echo "########### jmx client finished, terminating ab clients..."
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo -n "########### going to stop load generator at $client_machine..."
+ ssh -n jerseyrobot@$client_machine 'if ! test -e `ps h o pid -Cwrk`; then kill -s INT `ps h o pid -Cwrk` ; fi'
+ echo " done."
+ done
+
+ echo "########### terminating test app..."
+ ssh jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-grizzly-runner && ./stop.sh)'
+
+ cleanupServer $SERVER_MACHINE
+
+ releaseRunnerAndGroup $actual_runner $group_id
+}
+
+#
+# test process start
+#
+
+removeOldCapturedData
+
+retrieveJmxClient
+
+prepareClients
+
+buildTestAppOnServers
+
+echo "########### Package (lib dir) all test case applications"
+for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ for app in ${APP_LIST[*]}; do
+ ssh jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/test-cases/'$app'; mkdir -p target/runner/lib; cd target/runner/lib; unzip ../../*.zip)'
+ done
+done
+
+echo "########### Build and package (lib dir) test runner"
+for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey; mvn -pl tests/performance/runners/jersey-grizzly-runner clean install; cd tests/performance/runners/jersey-grizzly-runner; mkdir -p lib; rm -f lib/*.jar; cd lib; unzip ../target/*.zip)' &
+done
+
+wait
+
+cleanupServers
+
+testLoop
+
+waitForTerminator
diff --git a/tests/performance/etc/hudson/jersey-performance-test-wls.sh b/tests/performance/etc/hudson/jersey-performance-test-wls.sh
new file mode 100644
index 0000000..1b76227
--- /dev/null
+++ b/tests/performance/etc/hudson/jersey-performance-test-wls.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+#
+# Environment setup:
+#
+# GIT_FETCH_COMMAND - specify GIT command to get sources to test, e.g. git checkout master && git pull
+# WEBLOGIC_OUI_URL - URL to download WLS installation jar from
+#
+# STATUS_DIR=$HOME/.hudson-jersey3-performance-test
+# mkdir -p $STATUS_DIR
+# source jersey-performance-test-common.sh
+# test machine sets: cfg#, group, server, clients
+# createMachineFiles 1 1 server1 client1a client1b
+# createMachineFiles 1 2 server2 client2a client2b
+# MEASUREMENT_DATA=~/MEASUREMENT_DATA
+#
+
+LOGS_DIR=$WORKSPACE/logs
+
+SERVER_PORT=7001
+
+function singleTest() {
+ echo "================================================================================="
+ echo "===== SINGLE TEST RUN, SERVER=$SERVER_MACHINE, loader=$ab_cmdline, app=$app, JMX_URI=$JMX_URI, group_id=$group_id ====="
+ echo "================================================================================="
+
+ echo "########### Start WLS server"
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-wls-runner; ./start.sh)' &
+
+ echo "########### waiting for WLS server start"
+ while [ ! `wget -q --server-response --no-proxy http://${SERVER_MACHINE}:7001 2>&1 | awk '/^ HTTP/{print $2}'` ]; do
+ sleep 5
+ echo "# ${SERVER_MACHINE}"
+ done
+
+ echo "########### going to deploy/start the test app $app"
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-wls-runner; ./deploy.sh $PWD/../../test-cases/'$app'/target/runner/'$app'.war)'
+
+ waitForGroupStatus $actual_runner $group_id "open"
+
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo "########### going to start load generator at $client_machine"
+ (sleep $WAIT_FOR_APP_STARTUP_SEC; ssh -n jerseyrobot@$client_machine "nohup $ab_cmdline" & ) &
+ done
+
+ echo "########### waiting $WARM_UP_SECONDS sec to warm up server"
+ sleep $WARM_UP_SECONDS
+
+ echo "########### warm up finished, terminating ab clients..."
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo -n "########### warm up finished, going to stop load generator at $client_machine..."
+ ssh -n jerseyrobot@$client_machine 'if ! test -e `ps h o pid -Cwrk`; then kill -s INT `ps h o pid -Cwrk` ; fi'
+ echo " done."
+ done
+
+ waitForGroupStatus $actual_runner $group_id "lock"
+
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo "########### going to start load generator at $client_machine again"
+ (ssh -n jerseyrobot@$client_machine "nohup $ab_cmdline" & ) &
+ done
+
+ echo "########### waiting before start capturing jmx data"
+ sleep $WAIT_FOR_APP_RUNNING_SEC
+
+ echo "########### starting jmx client to capture data"
+ if ! java -cp jmxclient.jar org.glassfish.jersey.tests.performance.jmxclient.Main $JMX_URI "$mbean" OneMinuteRate $SAMPLES $filename; then
+ echo "########### ERROR WHEN PROCESSING LINE#${LINE_NUMBER}, test-case: ${app}, mbean: ${mbean}, filename: ${filename}!"
+ fi
+
+ echo "########### jmx client finished, terminating ab clients..."
+ for client_machine in ${CLIENT_LIST[*]}; do
+ echo -n "########### going to stop load generator at $client_machine..."
+ ssh -n jerseyrobot@$client_machine 'if ! test -e `ps h o pid -Cwrk`; then kill -s INT `ps h o pid -Cwrk` ; fi'
+ echo " done."
+ done
+
+ echo "########### terminating test app..."
+ ssh jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-wls-runner && ./stop.sh)'
+
+ echo "########### copy server and domain logs to hudson slave..."
+ just_filename=`echo ${filename} | sed -e 's/\.[^.]*$//'`
+ scp jerseyrobot@${SERVER_MACHINE}:workspace/jersey/tests/performance/runners/jersey-wls-runner/target/server.log $LOGS_DIR/${just_filename}-server.log
+ scp jerseyrobot@${SERVER_MACHINE}:workspace/jersey/tests/performance/runners/jersey-wls-runner/target/domain.log $LOGS_DIR/${just_filename}-domain.log
+
+ cleanupServer $SERVER_MACHINE
+
+ releaseRunnerAndGroup $actual_runner $group_id
+}
+
+#
+# test process start
+#
+
+mkdir -p $LOGS_DIR
+rm -f $LOGS_DIR/*
+
+removeOldCapturedData
+
+retrieveJmxClient
+
+prepareClients
+
+buildTestAppOnServers
+
+echo "########### Prepare war files of all test case applications"
+for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ for app in ${APP_LIST[*]}; do
+ ssh jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/test-cases/'$app'; mkdir -p target/runner; cp target/*.war target/runner/'$app'.war)'
+ done
+done
+
+echo "########### Install WLS server"
+for SERVER_MACHINE in ${SERVER_LIST[@]}; do
+ ssh -n jerseyrobot@${SERVER_MACHINE} '(cd workspace/jersey/tests/performance/runners/jersey-wls-runner; ./install.sh '$WEBLOGIC_OUI_URL')' &
+done
+
+wait
+
+cleanupServers
+
+testLoop
+
+waitForTerminator
diff --git a/tests/performance/jmx-client/pom.xml b/tests/performance/jmx-client/pom.xml
new file mode 100644
index 0000000..f497879
--- /dev/null
+++ b/tests/performance/jmx-client/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.glassfish.jersey.test.performance</groupId>
+ <artifactId>jmxclient</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>JmxClient</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+</project>
diff --git a/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
new file mode 100644
index 0000000..9cfafb4
--- /dev/null
+++ b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.jmxclient;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * JMX Client entry point.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+
+// e.g. "service:jmx:rmi:///jndi/rmi://sysifos.cz.oracle.com:11112/jmxrmi"
+ final String jmxUrl = args[0];
+// e.g. "org.glassfish.jersey.test.performance.interceptor.dynamic:type=DynamicallyBoundInterceptorResource,name=gets"
+ final String mBeanName = args[1];
+// e.g. "OneMinuteRate"
+ final String mBeanAttrName = args[2];
+// e.g. 50
+ final int sampleCount = Integer.parseInt(args[3]);
+// e.g. "phishing.properties"
+ final String propertiesFile = args[4];
+
+ System.out.printf("JMX URL = %s\nMBean = %s\nattribute = %s\nsamples = %d\nfilename = %s\n"
+ + "Going to connect...\n",
+ jmxUrl, mBeanName, mBeanAttrName, sampleCount, propertiesFile);
+
+ final JMXServiceURL url = new JMXServiceURL(jmxUrl);
+ final JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
+ final MBeanServerConnection mBeanServer = jmxc.getMBeanServerConnection();
+ final ObjectName mBeanObjectName = new ObjectName(mBeanName);
+
+ System.out.println("Connected...");
+
+ double totalSum = 0;
+ int samplesTaken = 0;
+
+ for (int i = 0; i < sampleCount; i++) {
+ Thread.sleep(5000);
+
+ Double sample = (Double) mBeanServer.getAttribute(mBeanObjectName, mBeanAttrName);
+
+ System.out.printf("OMR[%d]=%f\n", i, sample);
+
+ totalSum += sample;
+ samplesTaken++;
+ }
+
+ jmxc.close();
+
+ final double result = totalSum / samplesTaken;
+ writeResult(result, propertiesFile);
+
+ System.out.printf("\nAverage=%f\n", result);
+ }
+
+ private static void writeResult(double resultValue, String propertiesFile) throws IOException {
+ Properties resultProps = new Properties();
+ resultProps.put("YVALUE", Double.toString(resultValue));
+ resultProps.store(new FileOutputStream(propertiesFile), null);
+ }
+}
diff --git a/tests/performance/pom.xml b/tests/performance/pom.xml
new file mode 100644
index 0000000..6434cf2
--- /dev/null
+++ b/tests/performance/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.performance</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-performance</name>
+
+ <description>
+ Performance tests.
+ </description>
+
+ <modules>
+ <module>benchmarks</module>
+ <module>runners</module>
+ <module>test-cases</module>
+ <module>tools</module>
+ </modules>
+
+</project>
diff --git a/tests/performance/runners/jersey-grizzly-runner/pom.xml b/tests/performance/runners/jersey-grizzly-runner/pom.xml
new file mode 100644
index 0000000..4718865
--- /dev/null
+++ b/tests/performance/runners/jersey-grizzly-runner/pom.xml
@@ -0,0 +1,94 @@
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.runners</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+
+ <artifactId>jersey-grizzly-runner</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-grizzly-runner</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <archive>
+ <index>true</index>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>org.glassfish.jersey.tests.performance.runners.JerseyGrizzlyRunner</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.glassfish.jersey.tests.performance.runners.JerseyGrizzlyRunner</mainClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/zip-with-jars.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <!-- this is used for inheritance merges -->
+ <phase>package</phase>
+ <!-- append to the packaging phase. -->
+ <goals>
+ <goal>attached</goal>
+ <!-- goals == mojos -->
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/runners/jersey-grizzly-runner/src/main/assembly/zip-with-jars.xml b/tests/performance/runners/jersey-grizzly-runner/src/main/assembly/zip-with-jars.xml
new file mode 100644
index 0000000..92a2a73
--- /dev/null
+++ b/tests/performance/runners/jersey-grizzly-runner/src/main/assembly/zip-with-jars.xml
@@ -0,0 +1,35 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>zip-with-jars</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/</outputDirectory>
+ <useProjectArtifact>true</useProjectArtifact>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/tests/performance/runners/jersey-grizzly-runner/src/main/java/org/glassfish/jersey/tests/performance/runners/JerseyGrizzlyRunner.java b/tests/performance/runners/jersey-grizzly-runner/src/main/java/org/glassfish/jersey/tests/performance/runners/JerseyGrizzlyRunner.java
new file mode 100644
index 0000000..bc651cb
--- /dev/null
+++ b/tests/performance/runners/jersey-grizzly-runner/src/main/java/org/glassfish/jersey/tests/performance/runners/JerseyGrizzlyRunner.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.runners;
+
+import java.net.URI;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
+import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
+
+/**
+ * Application class to start performance test web service at http://localhost:8080/ if the base URI
+ * is not passed via the second command line argument.
+ */
+public class JerseyGrizzlyRunner {
+
+ private static final URI BASE_URI = URI.create("http://localhost:8080/");
+
+ private static final int DEFAULT_SELECTORS = 4;
+ private static final int DEFAULT_WORKERS = 8;
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Jersey performance test web service application");
+
+ final String jaxRsApp = args.length > 0 ? args[0] : null;
+ //noinspection unchecked
+ final ResourceConfig resourceConfig = ResourceConfig
+ .forApplicationClass((Class<? extends Application>) Class.forName(jaxRsApp));
+ URI baseUri = args.length > 1 ? URI.create(args[1]) : BASE_URI;
+ int selectors = args.length > 2 ? Integer.parseInt(args[2]) : DEFAULT_SELECTORS;
+ int workers = args.length > 3 ? Integer.parseInt(args[3]) : DEFAULT_WORKERS;
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig, false);
+ final TCPNIOTransport transport = server.getListener("grizzly").getTransport();
+ transport.setSelectorRunnersCount(selectors);
+ transport.setWorkerThreadPoolConfig(ThreadPoolConfig.defaultConfig().setCorePoolSize(workers).setMaxPoolSize(workers));
+
+ server.start();
+
+ System.out.println(String.format("Application started.\nTry out %s\nHit Ctrl-C to stop it...",
+ baseUri));
+
+ while (server.isStarted()) {
+ Thread.sleep(600000);
+ }
+ }
+}
diff --git a/tests/performance/runners/jersey-grizzly-runner/start.sh b/tests/performance/runners/jersey-grizzly-runner/start.sh
new file mode 100644
index 0000000..76d45e4
--- /dev/null
+++ b/tests/performance/runners/jersey-grizzly-runner/start.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+LIBS=$(for l in `ls lib`; do echo -n lib/$l":";done)
+LIBS=`echo $LIBS | sed -es'/:$//'`
+
+APP=$(for l in `ls app`; do echo -n app/$l":";done)
+APP=`echo $APP | sed -es'/:$//'`
+
+nohup java -server -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m \
+ -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods \
+ -cp $APP:$LIBS \
+ -Djava.net.preferIPv4Stack=true \
+ -Dcom.sun.management.jmxremote \
+ -Dcom.sun.management.jmxremote.port=11112 \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false \
+ -Dcom.sun.management.jmxremote.local.only=false \
+ $JAVA_OPTIONS \
+ org.glassfish.jersey.tests.performance.runners.JerseyGrizzlyRunner $* &
+echo $! > grizzly.pid
+wait
diff --git a/tests/performance/runners/jersey-grizzly-runner/stop.sh b/tests/performance/runners/jersey-grizzly-runner/stop.sh
new file mode 100644
index 0000000..08ea49c
--- /dev/null
+++ b/tests/performance/runners/jersey-grizzly-runner/stop.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+if test -f grizzly.pid; then
+ kill -9 `cat grizzly.pid`
+ rm grizzly.pid
+fi
+
diff --git a/tests/performance/runners/jersey-wls-runner/deploy.sh b/tests/performance/runners/jersey-wls-runner/deploy.sh
new file mode 100644
index 0000000..261030b
--- /dev/null
+++ b/tests/performance/runners/jersey-wls-runner/deploy.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+FILE=$1
+
+TARGET=$PWD/target
+TEST_DOMAIN=`cat $TARGET/test_domain.txt`
+
+. $TEST_DOMAIN/bin/setDomainEnv.sh
+
+java weblogic.Deployer -username weblogic -password weblogic1 -deploy $FILE
diff --git a/tests/performance/runners/jersey-wls-runner/install.sh b/tests/performance/runners/jersey-wls-runner/install.sh
new file mode 100644
index 0000000..529efd8
--- /dev/null
+++ b/tests/performance/runners/jersey-wls-runner/install.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+WEBLOGIC_URL=$1
+
+TARGET=$PWD/target
+OPT=$TARGET/opt
+
+rm -rf $TARGET
+mkdir -p $OPT
+
+cd $TARGET
+rm -f wls.jar
+wget --no-proxy $WEBLOGIC_URL -O wls.jar
+
+cd $OPT
+java -jar $TARGET/wls.jar
+cd wls*
+
+MW_HOME=`pwd`
+echo $MW_HOME > $TARGET/mw_home.txt
+
+. $MW_HOME/wlserver/server/bin/setWLSEnv.sh
+
+TEST_DOMAIN=$MW_HOME/hudson_test_domain
+
+mkdir -p $TEST_DOMAIN
+cd $TEST_DOMAIN
+
diff --git a/tests/performance/runners/jersey-wls-runner/start.sh b/tests/performance/runners/jersey-wls-runner/start.sh
new file mode 100644
index 0000000..a08f7ef
--- /dev/null
+++ b/tests/performance/runners/jersey-wls-runner/start.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+TARGET=$PWD/target
+MW_HOME=`cat $TARGET/mw_home.txt`
+TEST_DOMAIN=$MW_HOME/hudson_test_domain
+DOMAIN_NAME=HudsonTestDomain
+SERVER_NAME=HudsonTestServer
+PID_FILE=$TARGET/wls.pid
+
+echo $TEST_DOMAIN > $TARGET/test_domain.txt
+
+cd $MW_HOME
+. $MW_HOME/wlserver/server/bin/setWLSEnv.sh
+
+rm -rf $TEST_DOMAIN
+mkdir -p $TEST_DOMAIN
+cd $TEST_DOMAIN
+
+rm -f $TARGET/autodeploy
+ln -s $TEST_DOMAIN/autodeploy $TARGET/autodeploy
+
+rm -f $TARGET/server.log
+rm -f $TARGET/domain.log
+ln -s $TEST_DOMAIN/servers/$SERVER_NAME/logs/$SERVER_NAME.log $TARGET/server.log
+ln -s $TEST_DOMAIN/servers/$SERVER_NAME/logs/$DOMAIN_NAME.log $TARGET/domain.log
+
+JAVA_OPTIONS="-javaagent:$HOME/jersey-perftest-agent.jar"
+
+yes | nohup java -server \
+ -Xms1024m \
+ -Xmx1024m \
+ -XX:MaxPermSize=256m \
+ -Dweblogic.Domain=$DOMAIN_NAME \
+ -Dweblogic.Name=$SERVER_NAME \
+ -Dweblogic.management.username=weblogic \
+ -Dweblogic.management.password=weblogic1 \
+ -Dweblogic.ListenPort=7001 \
+ -Djava.security.egd=file:/dev/./urandom \
+ -Djava.net.preferIPv4Stack=true \
+ -Dcom.sun.management.jmxremote \
+ -Dcom.sun.management.jmxremote.port=11112 \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false \
+ -Dcom.sun.management.jmxremote.local.only=false \
+ $JAVA_OPTIONS \
+ weblogic.Server &
+
+echo $! > $PID_FILE
+
+# wait for server to start
+echo "******** WAITING FOR SERVER TO START"
+while [ ! `wget -q --server-response --no-proxy http://localhost:7001 2>&1 | awk '/^ HTTP/{print $2}'` ]; do
+ sleep 5
+ echo "*"
+done
+echo "******** SERVER IS READY"
diff --git a/tests/performance/runners/jersey-wls-runner/stop.sh b/tests/performance/runners/jersey-wls-runner/stop.sh
new file mode 100644
index 0000000..5b7691c
--- /dev/null
+++ b/tests/performance/runners/jersey-wls-runner/stop.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+TARGET=$PWD/target
+PID_FILE=$TARGET/wls.pid
+
+if test -f $PID_FILE; then
+ kill -9 `cat $PID_FILE`
+ rm $PID_FILE
+fi
diff --git a/tests/performance/runners/pom.xml b/tests/performance/runners/pom.xml
new file mode 100644
index 0000000..d0dc4d0
--- /dev/null
+++ b/tests/performance/runners/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.performance.runners</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-performance-runners</name>
+
+ <description>
+ Performance test runners.
+ </description>
+
+ <modules>
+ <module>jersey-grizzly-runner</module>
+ </modules>
+</project>
diff --git a/tests/performance/test-cases/assemblies/pom.xml b/tests/performance/test-cases/assemblies/pom.xml
new file mode 100644
index 0000000..cdd2c46
--- /dev/null
+++ b/tests/performance/test-cases/assemblies/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>assemblies</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-assemblies</name>
+ <description>Jersey performance test-cases shared assembly types.</description>
+
+</project>
diff --git a/tests/performance/test-cases/assemblies/src/main/resources/assemblies/war.xml b/tests/performance/test-cases/assemblies/src/main/resources/assemblies/war.xml
new file mode 100644
index 0000000..37cc628
--- /dev/null
+++ b/tests/performance/test-cases/assemblies/src/main/resources/assemblies/war.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>war</id>
+ <formats>
+ <format>war</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/WEB-INF/lib</outputDirectory>
+ <useProjectArtifact>true</useProjectArtifact>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/webapp</directory>
+ <outputDirectory>/</outputDirectory>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/tests/performance/test-cases/assemblies/src/main/resources/assemblies/zip-with-jars.xml b/tests/performance/test-cases/assemblies/src/main/resources/assemblies/zip-with-jars.xml
new file mode 100644
index 0000000..e65f8f7
--- /dev/null
+++ b/tests/performance/test-cases/assemblies/src/main/resources/assemblies/zip-with-jars.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>zip-with-jars</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/</outputDirectory>
+ <useProjectArtifact>true</useProjectArtifact>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/tests/performance/test-cases/filter-dynamic/pom.xml b/tests/performance/test-cases/filter-dynamic/pom.xml
new file mode 100644
index 0000000..43208e4
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>filter-dynamic</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-filter-dynamic-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicFilterFeature.java b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicFilterFeature.java
new file mode 100644
index 0000000..6539149
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicFilterFeature.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.dynamic;
+
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+
+/**
+ * Dynamic feature to register custom filter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class DynamicFilterFeature implements DynamicFeature {
+
+ @Override
+ public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+ if (DynamicallyBoundFilterResource.class == resourceInfo.getResourceClass()) {
+ context.register(DynamicallyBoundFilter.class);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilter.java b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilter.java
new file mode 100644
index 0000000..c3da591
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.dynamic;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Custom filter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class DynamicallyBoundFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.hasEntity()) {
+ requestContext.setEntityStream(new SequenceInputStream(new ByteArrayInputStream("DYN_MATCH_IN".getBytes()),
+ requestContext.getEntityStream()));
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ if (responseContext.hasEntity()) {
+ responseContext.setEntity("" + responseContext.getEntity() + "DYN_MATCH_OUT", null, MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilterResource.java b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilterResource.java
new file mode 100644
index 0000000..0a647c8
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/DynamicallyBoundFilterResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.dynamic;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Filtered resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class DynamicallyBoundFilterResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/JaxRsApplication.java b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/JaxRsApplication.java
new file mode 100644
index 0000000..0e68c16
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/main/java/org/glassfish/jersey/tests/performance/filter/dynamic/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.dynamic;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(DynamicallyBoundFilterResource.class);
+ add(DynamicFilterFeature.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/filter-dynamic/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/filter-dynamic/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..11c53fe
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.filter.dynamic.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/filter-dynamic/src/test/java/org/glassfish/jersey/tests/performance/filter/dynamic/FilterTest.java b/tests/performance/test-cases/filter-dynamic/src/test/java/org/glassfish/jersey/tests/performance/filter/dynamic/FilterTest.java
new file mode 100644
index 0000000..7a31093
--- /dev/null
+++ b/tests/performance/test-cases/filter-dynamic/src/test/java/org/glassfish/jersey/tests/performance/filter/dynamic/FilterTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.dynamic;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class FilterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("textDYN_MATCH_OUT", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("DYN_MATCH_IN" + original + "DYN_MATCH_OUT", postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/filter-global/pom.xml b/tests/performance/test-cases/filter-global/pom.xml
new file mode 100644
index 0000000..21c00ea
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>filter-global</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-filter-global-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/GlobalFilter.java b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/GlobalFilter.java
new file mode 100644
index 0000000..5544482
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/GlobalFilter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.global;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Global custom filter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class GlobalFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.hasEntity()) {
+ requestContext.setEntityStream(new SequenceInputStream(new ByteArrayInputStream("PRE_MATCH_IN".getBytes()),
+ requestContext.getEntityStream()));
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ if (responseContext.hasEntity()) {
+ responseContext.setEntity("" + responseContext.getEntity() + "PRE_MATCH_OUT", null, MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/JaxRsApplication.java b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/JaxRsApplication.java
new file mode 100644
index 0000000..11eb07d
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.global;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(TextEntityResource.class);
+ add(GlobalFilter.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/TextEntityResource.java b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/TextEntityResource.java
new file mode 100644
index 0000000..de1ce75
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/src/main/java/org/glassfish/jersey/tests/performance/filter/global/TextEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.global;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class TextEntityResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/filter-global/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/filter-global/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..772373b
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.filter.global.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/filter-global/src/test/java/org/glassfish/jersey/tests/performance/filter/global/FilterTest.java b/tests/performance/test-cases/filter-global/src/test/java/org/glassfish/jersey/tests/performance/filter/global/FilterTest.java
new file mode 100644
index 0000000..d1fe5ad
--- /dev/null
+++ b/tests/performance/test-cases/filter-global/src/test/java/org/glassfish/jersey/tests/performance/filter/global/FilterTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.global;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class FilterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("textPRE_MATCH_OUT", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("PRE_MATCH_IN" + original + "PRE_MATCH_OUT", postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/filter-name/pom.xml b/tests/performance/test-cases/filter-name/pom.xml
new file mode 100644
index 0000000..227739a
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>filter-name</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-filter-name-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/Filtered.java b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/Filtered.java
new file mode 100644
index 0000000..8928b61
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/Filtered.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.name;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.NameBinding;
+
+/**
+ * Custom binding annotation.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@NameBinding
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Filtered {}
diff --git a/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/JaxRsApplication.java b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/JaxRsApplication.java
new file mode 100644
index 0000000..4d1ecc7
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.name;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(NameBoundFilterResource.class);
+ add(NameBoundFilter.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilter.java b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilter.java
new file mode 100644
index 0000000..7704c6f
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilter.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.name;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Custom filter.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Filtered
+public class NameBoundFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ if (requestContext.hasEntity()) {
+ requestContext.setEntityStream(new SequenceInputStream(new ByteArrayInputStream("NAM_MATCH_IN".getBytes()),
+ requestContext.getEntityStream()));
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ if (responseContext.hasEntity()) {
+ responseContext.setEntity("" + responseContext.getEntity() + "NAM_MATCH_OUT", null, MediaType.TEXT_PLAIN_TYPE);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilterResource.java b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilterResource.java
new file mode 100644
index 0000000..98c49af
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/main/java/org/glassfish/jersey/tests/performance/filter/name/NameBoundFilterResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.name;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Filtered resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+@Filtered
+public class NameBoundFilterResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/filter-name/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/filter-name/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fbe4121
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.filter.name.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/filter-name/src/test/java/org/glassfish/jersey/tests/performance/filter/name/FilterTest.java b/tests/performance/test-cases/filter-name/src/test/java/org/glassfish/jersey/tests/performance/filter/name/FilterTest.java
new file mode 100644
index 0000000..776d0af
--- /dev/null
+++ b/tests/performance/test-cases/filter-name/src/test/java/org/glassfish/jersey/tests/performance/filter/name/FilterTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.filter.name;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class FilterTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("textNAM_MATCH_OUT", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("NAM_MATCH_IN" + original + "NAM_MATCH_OUT", postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-dynamic/pom.xml b/tests/performance/test-cases/interceptor-dynamic/pom.xml
new file mode 100644
index 0000000..e962e03
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>interceptor-dynamic</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-interceptor-dynamic-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicInterceptorFeature.java b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicInterceptorFeature.java
new file mode 100644
index 0000000..1903b09
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicInterceptorFeature.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.dynamic;
+
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Custom feature to register interceptor.
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class DynamicInterceptorFeature implements DynamicFeature {
+
+ @Override
+ public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+ if (DynamicallyBoundInterceptorResource.class == resourceInfo.getResourceClass()) {
+ context.register(DynamicallyBoundInterceptor.class);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptor.java b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptor.java
new file mode 100644
index 0000000..0ce113e
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.dynamic;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * Custom interceptor.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class DynamicallyBoundInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(new SequenceInputStream(new ByteArrayInputStream("READ ".getBytes()), context.getInputStream()));
+ return context.proceed();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.getOutputStream().write("WRITE ".getBytes());
+ context.proceed();
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptorResource.java b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptorResource.java
new file mode 100644
index 0000000..a99d426
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/DynamicallyBoundInterceptorResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.dynamic;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Intercepted resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class DynamicallyBoundInterceptorResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/JaxRsApplication.java b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/JaxRsApplication.java
new file mode 100644
index 0000000..f01d2ab
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/main/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.dynamic;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(DynamicallyBoundInterceptorResource.class);
+ add(DynamicInterceptorFeature.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/interceptor-dynamic/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..633ed97
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.interceptor.dynamic.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/interceptor-dynamic/src/test/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/InterceptorTest.java b/tests/performance/test-cases/interceptor-dynamic/src/test/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/InterceptorTest.java
new file mode 100644
index 0000000..e93174c
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-dynamic/src/test/java/org/glassfish/jersey/tests/performance/interceptor/dynamic/InterceptorTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.dynamic;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InterceptorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("WRITE text", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("WRITE READ " + original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-global/pom.xml b/tests/performance/test-cases/interceptor-global/pom.xml
new file mode 100644
index 0000000..264dd02
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>interceptor-global</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-interceptor-global-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/CustomInterceptor.java b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/CustomInterceptor.java
new file mode 100644
index 0000000..32d1bb1
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/CustomInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.global;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * Custom interceptor.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+public class CustomInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(new SequenceInputStream(new ByteArrayInputStream("READ ".getBytes()), context.getInputStream()));
+ return context.proceed();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.getOutputStream().write("WRITE ".getBytes());
+ context.proceed();
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/JaxRsApplication.java b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/JaxRsApplication.java
new file mode 100644
index 0000000..21d7308
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.global;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(TextEntityResource.class);
+ add(CustomInterceptor.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/TextEntityResource.java b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/TextEntityResource.java
new file mode 100644
index 0000000..dab5710
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/src/main/java/org/glassfish/jersey/tests/performance/interceptor/global/TextEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.global;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class TextEntityResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-global/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/interceptor-global/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe64786
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.interceptor.global.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/interceptor-global/src/test/java/org/glassfish/jersey/tests/performance/interceptor/global/InterceptorTest.java b/tests/performance/test-cases/interceptor-global/src/test/java/org/glassfish/jersey/tests/performance/interceptor/global/InterceptorTest.java
new file mode 100644
index 0000000..6f00764
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-global/src/test/java/org/glassfish/jersey/tests/performance/interceptor/global/InterceptorTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.global;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InterceptorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("WRITE text", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("WRITE READ " + original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-name/pom.xml b/tests/performance/test-cases/interceptor-name/pom.xml
new file mode 100644
index 0000000..b08fecf
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>interceptor-name</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-interceptor-name-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/Intercepted.java b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/Intercepted.java
new file mode 100644
index 0000000..1185a0f
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/Intercepted.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.name;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.NameBinding;
+
+
+/**
+ * Custom annotation to bind interceptor.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@NameBinding
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Intercepted {}
diff --git a/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptedByNameResource.java b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptedByNameResource.java
new file mode 100644
index 0000000..d5fc36d
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptedByNameResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.name;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+@Intercepted
+public class InterceptedByNameResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/JaxRsApplication.java b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/JaxRsApplication.java
new file mode 100644
index 0000000..cc1334e
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.name;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(InterceptedByNameResource.class);
+ add(NameBoundInterceptor.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/NameBoundInterceptor.java b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/NameBoundInterceptor.java
new file mode 100644
index 0000000..0c17811
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/main/java/org/glassfish/jersey/tests/performance/interceptor/name/NameBoundInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.name;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+
+/**
+ * Custom interceptor.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Provider
+@Intercepted
+public class NameBoundInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(new SequenceInputStream(new ByteArrayInputStream("READ ".getBytes()), context.getInputStream()));
+ return context.proceed();
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.getOutputStream().write("WRITE ".getBytes());
+ context.proceed();
+ }
+}
diff --git a/tests/performance/test-cases/interceptor-name/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/interceptor-name/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5ffa433
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.interceptor.name.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/interceptor-name/src/test/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptorTest.java b/tests/performance/test-cases/interceptor-name/src/test/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptorTest.java
new file mode 100644
index 0000000..84c521e
--- /dev/null
+++ b/tests/performance/test-cases/interceptor-name/src/test/java/org/glassfish/jersey/tests/performance/interceptor/name/InterceptorTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.interceptor.name;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for intercepted text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InterceptorTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("WRITE text", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals("WRITE READ " + original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-custom-provider/pom.xml b/tests/performance/test-cases/mbw-custom-provider/pom.xml
new file mode 100644
index 0000000..2077e42
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/pom.xml
@@ -0,0 +1,61 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>custom-provider</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-custom-provider-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/JaxRsApplication.java b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/JaxRsApplication.java
new file mode 100644
index 0000000..d865298
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/JaxRsApplication.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.custom;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(PersonResource.class);
+ add(PersonProvider.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/Person.java b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/Person.java
new file mode 100644
index 0000000..105dbb7
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/Person.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.custom;
+
+import java.util.Objects;
+
+/**
+ * Test data bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonProvider.java b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonProvider.java
new file mode 100644
index 0000000..8e29399
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonProvider.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.custom;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+/**
+ * Custom message body worker.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Produces("application/person")
+@Consumes("application/person")
+public class PersonProvider implements MessageBodyWriter<Person>, MessageBodyReader<Person> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
+ return type == Person.class;
+ }
+
+ @Override
+ public long getSize(Person t, Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
+ return getByteRepresentation(t).length;
+ }
+
+ @Override
+ public void writeTo(Person t,
+ Class<?> type,
+ Type type1,
+ Annotation[] antns,
+ MediaType mt,
+ MultivaluedMap<String, Object> mm,
+ OutputStream out) throws IOException, WebApplicationException {
+ out.write(getByteRepresentation(t));
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
+ return type == Person.class;
+ }
+
+ @Override
+ public Person readFrom(Class<Person> type,
+ Type type1,
+ Annotation[] antns,
+ MediaType mt,
+ MultivaluedMap<String, String> mm,
+ InputStream in) throws IOException, WebApplicationException {
+ Person result = new Person();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ final String nameLine = reader.readLine();
+ result.name = nameLine.substring(nameLine.indexOf(": ") + 2);
+ final String ageLine = reader.readLine();
+ result.age = Integer.parseInt(ageLine.substring(ageLine.indexOf(": ") + 2));
+ final String addressLine = reader.readLine();
+ result.address = addressLine.substring(addressLine.indexOf(": ") + 2);
+
+ return result;
+ }
+
+ private byte[] getByteRepresentation(Person t) {
+ return String.format("name: %s\nage: %d\naddress: %s", t.name, t.age, t.address).getBytes();
+ }
+}
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonResource.java b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonResource.java
new file mode 100644
index 0000000..59196c1
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.custom;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Person resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes("application/person")
+@Produces("application/person")
+public class PersonResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person text) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Mozart", 21, "Salzburg");
+ }
+}
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-custom-provider/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..db2c84b
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.custom.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-custom-provider/src/test/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonEntityTest.java b/tests/performance/test-cases/mbw-custom-provider/src/test/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonEntityTest.java
new file mode 100644
index 0000000..69aaf37
--- /dev/null
+++ b/tests/performance/test-cases/mbw-custom-provider/src/test/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonEntityTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.custom;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for json resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class PersonEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(PersonProvider.class);
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Mozart", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth")};
+ for (Person original : testData) {
+ final Person postResponse = target().request().post(Entity.entity(original, "application/person"), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request()
+ .put(Entity.entity(new Person("Jules", 12, "Paris"), "application/person"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-jackson/pom.xml b/tests/performance/test-cases/mbw-json-jackson/pom.xml
new file mode 100644
index 0000000..9121b28
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/pom.xml
@@ -0,0 +1,65 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>json-jackson</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-json-jackson-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java
new file mode 100644
index 0000000..a85709d
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.jackson.JacksonFeature;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(JsonEntityResource.class);
+ add(JacksonFeature.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java
new file mode 100644
index 0000000..c945291
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public class JsonEntityResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person person) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Wolfgang", 21, "Salzburg");
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java
new file mode 100644
index 0000000..b3af2b0
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import java.util.Objects;
+
+/**
+ * Test data bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-jackson/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-json-jackson/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..88eea6c
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-json-jackson/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java b/tests/performance/test-cases/mbw-json-jackson/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java
new file mode 100644
index 0000000..2a25db3
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-jackson/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for json resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JsonEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(JacksonFeature.class);
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Wolfgang", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth") };
+ for (Person original : testData) {
+ final Person postResponse = target().request().post(Entity.json(original), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.json(new Person("Jules", 12, "Paris")));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-moxy/pom.xml b/tests/performance/test-cases/mbw-json-moxy/pom.xml
new file mode 100644
index 0000000..0dd8244
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/pom.xml
@@ -0,0 +1,61 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>json-moxy</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-json-moxy-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java
new file mode 100644
index 0000000..76f96dc
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JaxRsApplication.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(JsonEntityResource.class);
+ add(MoxyJsonFeature.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java
new file mode 100644
index 0000000..b7afc36
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public class JsonEntityResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person person) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Wolfgang", 21, "Salzburg");
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java
new file mode 100644
index 0000000..b3af2b0
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/json/Person.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import java.util.Objects;
+
+/**
+ * Test data bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-json-moxy/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-json-moxy/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..88eea6c
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.json.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-json-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java b/tests/performance/test-cases/mbw-json-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java
new file mode 100644
index 0000000..acf2c42
--- /dev/null
+++ b/tests/performance/test-cases/mbw-json-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/json/JsonEntityTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.json;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for json resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JsonEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(MoxyJsonFeature.class);
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Wolfgang", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth") };
+ for (Person original : testData) {
+ final Person postResponse = target().request().post(Entity.json(original), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.json(new Person("Jules", 12, "Paris")));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-kryo/pom.xml b/tests/performance/test-cases/mbw-kryo/pom.xml
new file mode 100644
index 0000000..87d89c0
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/pom.xml
@@ -0,0 +1,61 @@
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>mbw-kryo</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-mbw-kryo-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-kryo</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/JaxRsApplication.java b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/JaxRsApplication.java
new file mode 100644
index 0000000..26eef29
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/JaxRsApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.kryo;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>() {{
+ add(PersonResource.class);
+ }};
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+
+}
diff --git a/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/Person.java b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/Person.java
new file mode 100644
index 0000000..8dc8d9e
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/Person.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.kryo;
+
+import java.util.Objects;
+
+/**
+ * Test data bean.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResource.java b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResource.java
new file mode 100644
index 0000000..f465365
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/src/main/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.kryo;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * Test resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+@Path("/")
+@Consumes("application/x-kryo")
+@Produces("application/x-kryo")
+public class PersonResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person person) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Wolfgang", 21, "Salzburg");
+ }
+
+}
diff --git a/tests/performance/test-cases/mbw-kryo/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-kryo/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..a875b70
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.kryo.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-kryo/src/test/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResourceTest.java b/tests/performance/test-cases/mbw-kryo/src/test/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResourceTest.java
new file mode 100644
index 0000000..bf03e8b
--- /dev/null
+++ b/tests/performance/test-cases/mbw-kryo/src/test/java/org/glassfish/jersey/tests/performance/mbw/kryo/PersonResourceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.kryo;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for kryo resource.
+ *
+ * @author Libor Kramolis (libor.kramolis at oracle.com)
+ */
+public class PersonResourceTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Wolfgang", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth")};
+ for (Person original : testData) {
+ final Person postResponse = target().request()
+ .post(Entity.entity(original, "application/x-kryo"), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.entity(new Person("Jules", 12, "Paris"),
+ "application/x-kryo"));
+ assertEquals(204, putResponse.getStatus());
+ }
+
+}
diff --git a/tests/performance/test-cases/mbw-text-plain/pom.xml b/tests/performance/test-cases/mbw-text-plain/pom.xml
new file mode 100644
index 0000000..e97d4c7
--- /dev/null
+++ b/tests/performance/test-cases/mbw-text-plain/pom.xml
@@ -0,0 +1,61 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>text-plain</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-text-plain-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/JaxRsApplication.java b/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/JaxRsApplication.java
new file mode 100644
index 0000000..d6651e6
--- /dev/null
+++ b/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/JaxRsApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.text;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>() {{
+ add(TextEntityResource.class);
+ }};
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityResource.java b/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityResource.java
new file mode 100644
index 0000000..65af72c
--- /dev/null
+++ b/tests/performance/test-cases/mbw-text-plain/src/main/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.text;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class TextEntityResource {
+
+ @POST
+ public String echo(final String text) {
+ return text;
+ }
+
+ @PUT
+ public void put(final String text) {
+ }
+
+ @GET
+ public String get() {
+ return "text";
+ }
+}
diff --git a/tests/performance/test-cases/mbw-text-plain/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-text-plain/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..8476905
--- /dev/null
+++ b/tests/performance/test-cases/mbw-text-plain/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.text.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-text-plain/src/test/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityTest.java b/tests/performance/test-cases/mbw-text-plain/src/test/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityTest.java
new file mode 100644
index 0000000..fb6ecb4
--- /dev/null
+++ b/tests/performance/test-cases/mbw-text-plain/src/test/java/org/glassfish/jersey/tests/performance/mbw/text/TextEntityTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.text;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for text plain resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class TextEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final String getResponse = target().request().get(String.class);
+ assertEquals("text", getResponse);
+ }
+
+ @Test
+ public void testPost() {
+ final String[] testData = new String[] {"one", "two", "three" };
+ for (String original : testData) {
+ final String postResponse = target().request().post(Entity.text(original), String.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.text("text"));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/pom.xml b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
new file mode 100644
index 0000000..9644471
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
@@ -0,0 +1,60 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>xml-jaxb</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-xml-jaxb-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java
new file mode 100644
index 0000000..94a47ee
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>() {{
+ add(XmlEntityResource.class);
+ }};
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java
new file mode 100644
index 0000000..8d9f6ff
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import java.util.Objects;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Test data bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@XmlRootElement
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java
new file mode 100644
index 0000000..eaf625c
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.APPLICATION_XML)
+@Produces(MediaType.APPLICATION_XML)
+public class XmlEntityResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person person) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Wolfgang", 21, "Salzburg");
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-xml-jaxb/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2a80019
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java b/tests/performance/test-cases/mbw-xml-jaxb/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java
new file mode 100644
index 0000000..8982902
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-jaxb/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for XML resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class XmlEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Wolfgang", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth") };
+ for (Person original : testData) {
+ final Person postResponse = target().request().post(Entity.xml(original), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.xml(new Person("Jules", 12, "Paris")));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-moxy/pom.xml b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
new file mode 100644
index 0000000..2b40b84
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
@@ -0,0 +1,60 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>xml-moxy</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-xml-moxy-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java
new file mode 100644
index 0000000..0de51b3
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/JaxRsApplication.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(XmlEntityResource.class);
+ add(MoxyXmlFeature.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java
new file mode 100644
index 0000000..2909ac5
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/Person.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import java.util.Objects;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Test data bean.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@XmlRootElement
+public class Person {
+
+ public String name;
+ public int age;
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 19 * hash + Objects.hashCode(this.name);
+ hash = 19 * hash + this.age;
+ hash = 19 * hash + Objects.hashCode(this.address);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Person other = (Person) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (this.age != other.age) {
+ return false;
+ }
+ return (Objects.equals(this.address, other.address));
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java
new file mode 100644
index 0000000..a28abe7
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/src/main/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityResource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+@Consumes(MediaType.APPLICATION_XML)
+@Produces(MediaType.APPLICATION_XML)
+public class XmlEntityResource {
+
+ @POST
+ public Person echo(final Person person) {
+ return person;
+ }
+
+ @PUT
+ public void put(final Person person) {
+ }
+
+ @GET
+ public Person get() {
+ return new Person("Wolfgang", 21, "Salzburg");
+ }
+}
diff --git a/tests/performance/test-cases/mbw-xml-moxy/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/mbw-xml-moxy/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2a80019
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.mbw.xml.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/mbw-xml-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java b/tests/performance/test-cases/mbw-xml-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java
new file mode 100644
index 0000000..9fabc89
--- /dev/null
+++ b/tests/performance/test-cases/mbw-xml-moxy/src/test/java/org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.mbw.xml;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
+import org.glassfish.jersey.test.JerseyTest;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+/**
+ * Test for XML resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class XmlEntityTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.register(MoxyXmlFeature.class);
+ }
+
+ @Test
+ public void testGet() {
+ final Person getResponse = target().request().get(Person.class);
+ assertEquals("Wolfgang", getResponse.name);
+ assertEquals(21, getResponse.age);
+ assertEquals("Salzburg", getResponse.address);
+ }
+
+ @Test
+ public void testPost() {
+ final Person[] testData = new Person[] {new Person("Joseph", 23, "Nazareth"), new Person("Mary", 18, "Nazareth") };
+ for (Person original : testData) {
+ final Person postResponse = target().request().post(Entity.xml(original), Person.class);
+ assertEquals(original, postResponse);
+ }
+ }
+
+ @Test
+ public void testPut() {
+ final Response putResponse = target().request().put(Entity.xml(new Person("Jules", 12, "Paris")));
+ assertEquals(204, putResponse.getStatus());
+ }
+}
diff --git a/tests/performance/test-cases/monitoring/pom.xml b/tests/performance/test-cases/monitoring/pom.xml
new file mode 100644
index 0000000..3b1404b
--- /dev/null
+++ b/tests/performance/test-cases/monitoring/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.glassfish.jersey.test.performance.monitoring</groupId>
+ <artifactId>monitoring</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>monitoring-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <version>2.1.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.5</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>14.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.6.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/zip-with-jars.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <!-- this is used for inheritance merges -->
+ <phase>package</phase>
+ <!-- append to the packaging phase. -->
+ <goals>
+ <goal>attached</goal>
+ <!-- goals == mojos -->
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <inherited>true</inherited>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <showWarnings>false</showWarnings>
+ <fork>false</fork>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/JerseyApp.java b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/JerseyApp.java
new file mode 100644
index 0000000..a5e97b4
--- /dev/null
+++ b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/JerseyApp.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.monitoring;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.model.*;
+import org.glassfish.jersey.server.model.Resource;
+
+/**
+ * Application class to start performance test web service at http://localhost:8080/ if the base URI
+ * is not passed via the first command line argument.
+ */
+public class JerseyApp {
+
+ private static final URI BASE_URI = URI.create("http://localhost:8080/");
+ public static final String ROOT_PATH = "text";
+
+ public static void main(final String[] args) throws Exception {
+ System.out.println("Jersey performance test web service application");
+
+ final URI baseUri = args.length > 0 ? URI.create(args[0]) : BASE_URI;
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, createResourceConfig());
+
+ System.out.println(String.format("Application started.\nTry out %s%s\nHit Ctrl-C to stop it...",
+ baseUri, ROOT_PATH));
+
+ while (server.isStarted()) {
+ Thread.sleep(600000);
+ }
+ }
+
+ private static ResourceConfig createResourceConfig() {
+ final Set<Resource> resources = new HashSet<>();
+ for (int i = 0; i < 10; i++) {
+ resources.add(Resource.builder(org.glassfish.jersey.tests.performance.monitoring.Resource.class)
+ .path("" + i)
+ .build());
+ }
+
+ return new ResourceConfig()
+ .property(ServerProperties.MONITORING_STATISTICS_ENABLED, true)
+ .property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, true)
+ .registerResources(resources);
+ }
+}
diff --git a/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/Resource.java b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/Resource.java
new file mode 100644
index 0000000..6956ec8
--- /dev/null
+++ b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/Resource.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.monitoring;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * @author Michal Gajdos
+ */
+@Path("/")
+@Produces("text/plain")
+public class Resource {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @GET
+ @Path("sub")
+ public String subget() {
+ return "sub-get";
+ }
+
+ @POST
+ public String post(final String post) {
+ return post;
+ }
+
+ @POST
+ @Path("sub")
+ public String subpost(final String post) {
+ return post;
+ }
+
+ @PUT
+ public String put(final String put) {
+ return put;
+ }
+
+ @PUT
+ @Path("sub")
+ public String subput(final String put) {
+ return put;
+ }
+
+ @DELETE
+ @Path("{id}")
+ public String delete(final String delete) {
+ return delete;
+ }
+
+ @DELETE
+ @Path("sub/{id}")
+ public String subdelete(final String delete) {
+ return delete;
+ }
+
+ @Path("locator")
+ public Class<SubResourceLocator> locator() {
+ return SubResourceLocator.class;
+ }
+}
diff --git a/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/SubResourceLocator.java b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/SubResourceLocator.java
new file mode 100644
index 0000000..0172930
--- /dev/null
+++ b/tests/performance/test-cases/monitoring/src/main/java/org/glassfish/jersey/tests/performance/monitoring/SubResourceLocator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.monitoring;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+
+/**
+ * @author Michal Gajdos
+ */
+public class SubResourceLocator {
+
+ @GET
+ public String get() {
+ return "get";
+ }
+
+ @POST
+ public String post(final String post) {
+ return post;
+ }
+
+ @PUT
+ public String put(final String put) {
+ return put;
+ }
+
+ @DELETE
+ @Path("{id}")
+ public String delete(final String delete) {
+ return delete;
+ }
+}
diff --git a/tests/performance/test-cases/monitoring/start.sh b/tests/performance/test-cases/monitoring/start.sh
new file mode 100644
index 0000000..5554544
--- /dev/null
+++ b/tests/performance/test-cases/monitoring/start.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+LIBS=$(for l in `ls lib`; do echo -n lib/$l":";done)
+LIBS=`echo $LIBS | sed -es'/:$//'`
+
+java -server -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m \
+ -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods \
+ -cp $LIBS \
+ -Djava.net.preferIPv4Stack=true \
+ -Dcom.sun.management.jmxremote \
+ -Dcom.sun.management.jmxremote.port=11112 \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false \
+ -Dcom.sun.management.jmxremote.local.only=false \
+ org.glassfish.jersey.tests.performance.monitoring.JerseyApp $1
diff --git a/tests/performance/test-cases/param-srl/pom.xml b/tests/performance/test-cases/param-srl/pom.xml
new file mode 100644
index 0000000..2baddfd
--- /dev/null
+++ b/tests/performance/test-cases/param-srl/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>param-srl</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-param-srl</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/JaxRsApplication.java b/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/JaxRsApplication.java
new file mode 100644
index 0000000..c6dc78d
--- /dev/null
+++ b/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/JaxRsApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.param.srl;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>() {{
+ add(SrlResource.class);
+ }};
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/SrlResource.java b/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/SrlResource.java
new file mode 100644
index 0000000..2b06e62
--- /dev/null
+++ b/tests/performance/test-cases/param-srl/src/main/java/org/glassfish/jersey/tests/performance/param/srl/SrlResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.param.srl;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Test resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("/")
+public class SrlResource {
+
+ public static class SubResource {
+
+ String p;
+
+ SubResource(String p) {
+ this.p = p;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String get(@MatrixParam("m") final String m, @QueryParam("q") final String q) {
+ return String.format("p=%s, m=%s, q=%s", p, m, q);
+ }
+ }
+
+ @Path("srl/{p}")
+ public SubResource locator(@PathParam("p") String p) {
+ return new SubResource(p);
+ }
+
+ @GET
+ @Path("srm/{p}")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String get(@PathParam("p") final String p, @MatrixParam("m") final String m, @QueryParam("q") final String q) {
+ return String.format("p=%s, m=%s, q=%s", p, m, q);
+ }
+}
diff --git a/tests/performance/test-cases/param-srl/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/param-srl/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1e27b3b
--- /dev/null
+++ b/tests/performance/test-cases/param-srl/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.param.srl.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/param-srl/src/test/java/org/glassfish/jersey/tests/performance/param/srl/SrlSrmTest.java b/tests/performance/test-cases/param-srl/src/test/java/org/glassfish/jersey/tests/performance/param/srl/SrlSrmTest.java
new file mode 100644
index 0000000..d4ad937
--- /dev/null
+++ b/tests/performance/test-cases/param-srl/src/test/java/org/glassfish/jersey/tests/performance/param/srl/SrlSrmTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.param.srl;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for SRL/SRM resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class SrlSrmTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testSrmSrl() {
+ String[][] testData = new String[][] {
+ {"one", "two", "three"},
+ {"four", "green", "top"},
+ {"bottom", "beauty", "mash"},
+ };
+
+ for (String[] input : testData) {
+ final String srlResponse = target().path("srl").path(input[0]).matrixParam("m", input[1]).queryParam("q", input[2])
+ .request().get(String.class);
+ final String srmResponse = target().path("srm").path(input[0]).matrixParam("m", input[1]).queryParam("q", input[2])
+ .request().get(String.class);
+ assertEquals(srlResponse, srmResponse);
+ }
+ }
+}
diff --git a/tests/performance/test-cases/pom.xml b/tests/performance/test-cases/pom.xml
new file mode 100644
index 0000000..6e29029
--- /dev/null
+++ b/tests/performance/test-cases/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests-performance-testcase</name>
+
+ <description>
+ Performance test cases.
+ </description>
+
+ <modules>
+ <module>assemblies</module>
+ <module>filter-dynamic</module>
+ <module>filter-global</module>
+ <module>filter-name</module>
+ <module>interceptor-dynamic</module>
+ <module>interceptor-global</module>
+ <module>interceptor-name</module>
+ <module>mbw-custom-provider</module>
+ <module>mbw-json-jackson</module>
+ <module>mbw-json-moxy</module>
+ <module>mbw-kryo</module>
+ <module>mbw-text-plain</module>
+ <module>mbw-xml-jaxb</module>
+ <module>mbw-xml-moxy</module>
+ <module>param-srl</module>
+ <module>proxy-injection</module>
+ </modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <dependencies>
+ <!-- Contains shared performance test-cases assembly descriptors -->
+ <dependency>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>assemblies</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <!-- this is used for inheritance merges -->
+ <phase>package</phase>
+ <!-- append to the packaging phase. -->
+ <goals>
+ <goal>attached</goal>
+ <!-- goals == mojos -->
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <!-- Reference to a descriptor in org.glassfish.jersey.tests.performance.testcases:assemblies module -->
+ <descriptorRef>zip-with-jars</descriptorRef>
+ <descriptorRef>war</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+</project>
diff --git a/tests/performance/test-cases/proxy-injection/pom.xml b/tests/performance/test-cases/proxy-injection/pom.xml
new file mode 100644
index 0000000..2a64052
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>proxy-injection</artifactId>
+ <packaging>jar</packaging>
+
+ <name>jersey-tests-performance-proxy-injection-test</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/FieldInjectedResource.java b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/FieldInjectedResource.java
new file mode 100644
index 0000000..ff024f7
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/FieldInjectedResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.proxy.injection;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Test resource to test field injected proxy-able parameters.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("field-injected")
+@Produces(MediaType.TEXT_PLAIN)
+public class FieldInjectedResource {
+
+ @Context
+ SecurityContext securityContext;
+ @Context
+ UriInfo uriInfo;
+ @Context
+ HttpHeaders httpHeaders;
+ @Context
+ Request request;
+
+ @GET
+ @Path("without-parameters")
+ public String getProxy() {
+ return String.format("sc: %s\nui: %s\nhh: %s\nreq: %s",
+ securityContext.getClass(), uriInfo.getClass(), httpHeaders.getClass(), request.getClass());
+ }
+}
diff --git a/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/JaxRsApplication.java b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/JaxRsApplication.java
new file mode 100644
index 0000000..c396a1a
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/JaxRsApplication.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.proxy.injection;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.core.Application;
+
+/**
+ * Test case JAX-RS application.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class JaxRsApplication extends Application {
+
+ static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>(){
+ {
+ add(FieldInjectedResource.class);
+ add(MethodInjectedResource.class);
+ }
+ };
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return APP_CLASSES;
+ }
+}
diff --git a/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/MethodInjectedResource.java b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/MethodInjectedResource.java
new file mode 100644
index 0000000..062e8fd
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/src/main/java/org/glassfish/jersey/tests/performance/proxy/injection/MethodInjectedResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.proxy.injection;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Test resource to compare resource method with and without injected method proxiable parameters.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@Path("method-injected")
+@Produces(MediaType.TEXT_PLAIN)
+public class MethodInjectedResource {
+
+ @GET
+ @Path("without-parameters")
+ public String getNoProxy() {
+ return "text";
+ }
+
+ @GET
+ @Path("all-parameters")
+ public String getProxy(@Context SecurityContext securityContext,
+ @Context UriInfo uriInfo,
+ @Context HttpHeaders httpHeaders,
+ @Context Request request) {
+ return String.format("sc: %s\nui: %s\nhh: %s\nreq: %s",
+ securityContext.getClass(), uriInfo.getClass(), httpHeaders.getClass(), request.getClass());
+ }
+}
diff --git a/tests/performance/test-cases/proxy-injection/src/main/webapp/WEB-INF/web.xml b/tests/performance/test-cases/proxy-injection/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..da3331d
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="3.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
+
+ <servlet>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.glassfish.jersey.tests.performance.proxy.injection.JaxRsApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JaxRsApplication</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/tests/performance/test-cases/proxy-injection/src/test/java/org/glassfish/jersey/tests/performance/proxy/injection/InjectedResourcesTest.java b/tests/performance/test-cases/proxy-injection/src/test/java/org/glassfish/jersey/tests/performance/proxy/injection/InjectedResourcesTest.java
new file mode 100644
index 0000000..2c9aeba
--- /dev/null
+++ b/tests/performance/test-cases/proxy-injection/src/test/java/org/glassfish/jersey/tests/performance/proxy/injection/InjectedResourcesTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.proxy.injection;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for field/method injected resource.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+public class InjectedResourcesTest extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ return new JaxRsApplication();
+ }
+
+ @Test
+ public void testSameTypesInjected() {
+ final String methodInjectedResponse = target().path("method-injected").path("all-parameters").request().get(String.class);
+ final String fieldInjectedResponse = target().path("field-injected").path("without-parameters").request()
+ .get(String.class);
+ assertEquals(methodInjectedResponse, fieldInjectedResponse);
+ }
+}
diff --git a/tests/performance/tools/README.html b/tests/performance/tools/README.html
new file mode 100644
index 0000000..3b44849
--- /dev/null
+++ b/tests/performance/tools/README.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+ <title>Test data generation tool for Jersey performance tests</title>
+
+ <!-- Bootstrap -->
+ <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
+</head>
+<body>
+
+<div class="container">
+ <div class="row">
+ <div class="col-lg-offset-1 col-lg-10">
+ <header class="page-header">
+ <h1>Test data generation tool for Jersey performance tests</small></h1>
+ </header>
+
+ <p>
+ This module contains a simple tool to generate data sets for performance testing. It generates three
+ distinct media types: xml, json and plain text, each in a variety of predefined data set sizes (1kB,
+ 5kB, 10kB, 1MB and optionally 1GB).
+ </p>
+
+ <p>
+ The generation of the largest files (1GB) is disabled by default to save disk space and shorten the
+ generation time. To enable it, change the value of the <pre>GENERATE_ALSO_GIGABYTE_DATASETS</pre>
+ constant in the <pre>TestDataGeneratorApp</pre> class to true.
+ </p>
+
+ <h2>Running the Example</h2>
+
+ <p>Run the example as follows:</p>
+ <blockquote>
+ <pre>mvn clean compile exec:java</pre>
+ </blockquote>
+
+ <p>
+ You can tweak the values of several constants in the <pre>TestDataGeneratorApp</pre> class before
+ launching the generation. For more information, please see the javadocs.
+ The above command launches a Grizzly server with the generation server-side app and runs a client with
+ predefined parameters against it.
+ </p>
+ </div>
+ </div>
+</div>
+
+<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
+</body>
+</html>
diff --git a/tests/performance/tools/pom.xml b/tests/performance/tools/pom.xml
new file mode 100644
index 0000000..9ea3a3a
--- /dev/null
+++ b/tests/performance/tools/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.jersey.tests.performance</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <groupId>org.glassfish.jersey.tests.performance.tools</groupId>
+ <artifactId>performance-test-tools</artifactId>
+ <packaging>jar</packaging>
+
+ <name>performance-test-tools</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.glassfish.jersey.tests.performance.tools.TestDataGeneratorApp</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ </build>
+</project>
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/ConstantTestValueGenerator.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/ConstantTestValueGenerator.java
new file mode 100644
index 0000000..eba4e1b
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/ConstantTestValueGenerator.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Implementation of {@link org.glassfish.jersey.tests.performance.tools.TestValueGenerator} producing constant results.
+ *
+ * Due to its constant nature, this strategy is not suitable for use with {@link java.util.Set}.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class ConstantTestValueGenerator extends TestValueGenerator {
+ private static final int intConstant = 123456789;
+ private static final int charConstant = 'x';
+ private static final String stringConstant = "Hello, world!";
+ private static final long longConstant = 987654321L;
+ private static final float floatConstant = 3.1415f;
+ private static final double doubleConstant = 3.1415926535;
+ private static final byte byteConstant = (byte) 127;
+ private static final short shortConstant = (short) 1024;
+ private static final boolean booleanConstant = true;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getInt() {
+ return intConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public char getChar() {
+ return charConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getString() {
+ return stringConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getLong() {
+ return longConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getFloat() {
+ return floatConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public double getDouble() {
+ return doubleConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte getByte() {
+ return byteConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public short getShort() {
+ return shortConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean getBoolean() {
+ return booleanConstant;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T> T getEnum(Class<T> enumType) {
+ T[] values = enumType.getEnumConstants();
+ if (values != null && values.length > 0) {
+ return values[0];
+ }
+ return null;
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/GenerateForTest.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/GenerateForTest.java
new file mode 100644
index 0000000..4b6fb27
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/GenerateForTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation to mark fields of a bean to be populated by
+ * {@link org.glassfish.jersey.tests.performance.tools.TestValueGenerator} during the test data generation process.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface GenerateForTest {
+ /** specifies how many elements should be created and added to an array/collection */
+ int length() default 1;
+
+ /** due to java type erasure, the type of the collection has to be explicitly specified */
+ Class<?> collectionMemberType() default Object.class;
+
+ /** if the bean contains a collection declared via its interface, the desired implementing class has to be specified */
+ Class<?> implementingClass() default Object.class;
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/Person.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/Person.java
new file mode 100644
index 0000000..9fafa2c
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/Person.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Person data bean, copied from mbw tests and annotated for the test data generation tool.
+ *
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ */
+@XmlRootElement
+public class Person {
+
+ @GenerateForTest
+ public String name;
+ @GenerateForTest
+ public int age;
+ @GenerateForTest
+ public String address;
+
+ public Person(String name, int age, String address) {
+ this.name = name;
+ this.age = age;
+ this.address = address;
+ }
+
+ public Person() {
+ }
+
+ @Override
+ public String toString() {
+ return "Person@" + Integer.toHexString(hashCode()) + "\nname=" + name + "\nage=" + age + "\nadress=" + address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Person person = (Person) o;
+
+ if (age != person.age) {
+ return false;
+ }
+ if (address != null ? !address.equals(person.address) : person.address != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(person.name) : person.name != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + age;
+ result = 31 * result + (address != null ? address.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/RandomTestValueGenerator.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/RandomTestValueGenerator.java
new file mode 100644
index 0000000..3f0f961
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/RandomTestValueGenerator.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.util.Random;
+
+/**
+ * Implementation of {@link org.glassfish.jersey.tests.performance.tools.TestValueGenerator} producing random results.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class RandomTestValueGenerator extends TestValueGenerator {
+ private static final int MAX_STRING_LENGTH = 50;
+
+ private static final Random random = new Random();
+ private static final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 _";
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T> T getEnum(Class<T> enumType) {
+ T[] enumValues = enumType.getEnumConstants();
+ return enumValues[random.nextInt(enumValues.length)];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getInt() {
+ return random.nextInt();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public char getChar() {
+ return (char) random.nextInt(Character.MAX_VALUE + 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getString() {
+ return randomString(random.nextInt(MAX_STRING_LENGTH));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getLong() {
+ return random.nextLong();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getFloat() {
+ return random.nextFloat();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public double getDouble() {
+ return random.nextDouble();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte getByte() {
+ return (byte) random.nextInt(Byte.MAX_VALUE + 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public short getShort() {
+ return (short) random.nextInt(Short.MAX_VALUE + 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean getBoolean() {
+ return random.nextBoolean();
+ }
+
+ private String randomString(int length) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ sb.append(characters.charAt(random.nextInt(characters.length())));
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBean.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBean.java
new file mode 100644
index 0000000..b3f0317
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBean.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Example of a complex testing bean.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+@XmlRootElement
+public class TestBean {
+
+ /* primitives */
+ @GenerateForTest
+ public byte bt;
+ @GenerateForTest
+ public short sh;
+ @GenerateForTest
+ public int i;
+ @GenerateForTest
+ public long l;
+ @GenerateForTest
+ public float f;
+ @GenerateForTest
+ public double d;
+ @GenerateForTest
+ public boolean bl;
+ @GenerateForTest
+ public char c;
+
+ /* primitive wrappers */
+ @GenerateForTest
+ public Byte wrapBt;
+ @GenerateForTest
+ public Short wrapSh;
+ @GenerateForTest
+ public Integer wrapI;
+ @GenerateForTest
+ public Long wrapL;
+ @GenerateForTest
+ public Float wrapF;
+ @GenerateForTest
+ public Double wrapD;
+ @GenerateForTest
+ public Boolean wrapBl;
+ @GenerateForTest
+ public Character wrapC;
+
+ /* arrays */
+ @GenerateForTest(length = 7)
+ public Integer[] array;
+
+ @GenerateForTest
+ public Date date;
+
+ /* 1D - collections */
+ @XmlElementWrapper(name = "StringElements")
+ @XmlElement(name = "StringElement")
+ @GenerateForTest(collectionMemberType = String.class, implementingClass = ArrayList.class, length = 10)
+ public List<String> stringList;
+
+ @XmlElementWrapper(name = "IntegerElements")
+ @XmlElement(name = "IntegerElement")
+ @GenerateForTest(collectionMemberType = Integer.class, length = 5)
+ public HashSet<Integer> integerSet;
+
+ /* enums */
+ @GenerateForTest
+ public TestBeanEnum en;
+
+ /* custom types */
+ @GenerateForTest
+ public TestBeanInfo inner;
+
+ /* recursive */
+ @GenerateForTest
+ public TestBean nextBean;
+
+ /* and what about those? */
+ // CharSequence cs;
+ // Object o;
+ // Map<String, String> map;
+
+ @Override
+ public String toString() {
+ return printContent(0);
+ }
+
+ public String printContent(int level) {
+ String pad = level == 0 ? "" : String.format("%1$" + level + "s", "");
+ StringBuffer buf = new StringBuffer();
+ buf.append(pad + "# TestBean[level=" + level + "]@" + Integer.toHexString(hashCode())).append("\n");
+
+ buf.append(pad + "# Primitives").append("\n");
+ buf.append(pad + "[" + bt + ", " + sh + ", " + i + ", " + l + ", " + f + ", " + d + ", " + bl + ", " + c + "]")
+ .append("\n");
+
+ buf.append(pad + "# Primitives wrappers").append("\n");
+ buf.append(pad + "[" + wrapBt + ", " + wrapSh + ", " + wrapI + ", " + wrapL + ", " + wrapF + ", " + wrapD + ", "
+ + wrapBl + ", " + wrapC + "]").append("\n");
+
+ buf.append(pad + "# Arrays").append("\n");
+ if (array != null) {
+ buf.append(pad + "array: ");
+ for (Integer i : array) {
+ buf.append(i + ", ");
+ }
+ buf.append("\n");
+ }
+
+ buf.append(pad + "# Collections").append("\n");
+ if (stringList != null) {
+ buf.append(pad + "stringList: ");
+ for (String s : stringList) {
+ buf.append(s + ", ");
+ }
+ buf.append("\n");
+ }
+ if (integerSet != null) {
+ buf.append(pad + "integerSet: ");
+ for (Integer i : integerSet) {
+ buf.append(i + ", ");
+ }
+ buf.append("\n");
+ }
+
+ if (date != null) {
+ buf.append(pad + "date: " + date).append("\n");
+ }
+
+ buf.append(pad + "# Enums").append("\n");
+ if (en != null) {
+ buf.append(pad + "en=" + en).append("\n");
+ }
+ buf.append(pad + "# Inner bean").append("\n");
+ if (inner != null) {
+ buf.append(inner.printContent(level + 1));
+ }
+ buf.append("\n");
+ buf.append(pad + "# Recursive bean").append("\n");
+ if (nextBean != null) {
+ buf.append(nextBean.printContent(level + 1));
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanCoordinates.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanCoordinates.java
new file mode 100644
index 0000000..7326b98
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanCoordinates.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Part of a complex test bean example, contained in {@link org.glassfish.jersey.tests.performance.tools.TestBeanInfo}
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestBeanCoordinates {
+ @GenerateForTest
+ public int x;
+ @GenerateForTest
+ public int y;
+
+ public String printContent(int level) {
+ String pad = String.format("%1$" + level + "s", "");
+ return (pad + "# " + this + "\n" + pad + "x:y=" + x + ":" + y);
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanEnum.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanEnum.java
new file mode 100644
index 0000000..4ba4dc9
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanEnum.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Nested type of {@link org.glassfish.jersey.tests.performance.tools.TestBean}
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public enum TestBeanEnum {
+ VALUE_1, VALUE_2, VALUE_3;
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanInfo.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanInfo.java
new file mode 100644
index 0000000..5dd6ccc
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestBeanInfo.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Nested testing bean, contained in {@link org.glassfish.jersey.tests.performance.tools.TestBean}
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestBeanInfo {
+
+ @GenerateForTest
+ public Integer someNumber;
+ @GenerateForTest
+ public int i; // same name as in the main bean, on purpose
+ @GenerateForTest
+ public TestBeanCoordinates coords; // another nested level
+
+ public String printContent(int level) {
+ String pad = String.format("%1$" + level + "s", "");
+ StringBuffer buf = new StringBuffer();
+ buf.append(pad + "# " + this).append("\n");
+ buf.append(pad + "someNumber=" + someNumber).append("\n");
+ buf.append(pad + "i=" + i).append("\n");
+ if (coords != null) {
+ buf.append(coords.printContent(level + 1));
+ }
+ return buf.toString();
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerationStrategy.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerationStrategy.java
new file mode 100644
index 0000000..ab6dc47
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerationStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Enum for test data generation strategies.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public enum TestDataGenerationStrategy {
+ CONSTANT,
+ RANDOM,
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerator.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerator.java
new file mode 100644
index 0000000..c30efa4
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGenerator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Instantiates and populates a bean with testing data.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestDataGenerator {
+
+ /**
+ *
+ * @param bean bean to be populated
+ * @param <T> type of the testing bean
+ * @throws ClassNotFoundException
+ * @throws IllegalAccessException
+ * @throws NoSuchMethodException
+ * @throws InvocationTargetException
+ * @throws InstantiationException
+ */
+ public static <T> void populateBeanByAnnotations(T bean) throws ReflectiveOperationException {
+ Field[] fields = bean.getClass().getDeclaredFields();
+ TestValueGenerator generator = TestValueGeneratorFactory.getGenerator(TestDataGenerationStrategy.RANDOM);
+ for (Field field : fields) {
+ GenerateForTest annotation = field.getAnnotation(GenerateForTest.class);
+ if (annotation != null) {
+ field.setAccessible(true);
+ field.set(bean, generator.getValueForType(field.getType(), annotation));
+ }
+ }
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorApp.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorApp.java
new file mode 100644
index 0000000..857c45f
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorApp.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.ext.ContextResolver;
+
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+
+/**
+ * Application for generating custom testing data files for Jersey performance tests.
+ *
+ * <p>Creates set of files containing plain text, json and xml in various predefined sizes:
+ * 1kB, 5kB, 10kB, 1MB and optionally 1GB. The 1GB file has to be enabled by changing the constant
+ * {@code GENERATE_ALSO_GIGABYTE_DATASETS} to true.</p>
+ *
+ * <p>The sizes are the MINIMAL sizes, the generation stops after reaching the given size,
+ * but does not truncate the most recently
+ * generated entity. For simple testing beans the size difference from the predefined treshold is minimal,
+ * whereas for very complex testing beans the difference can be significant.</p>
+ *
+ * <p>MOXy is used for creating XML and JSON from the testing beans.</p>
+ *
+ * <p>Run the generation by invoking {@code mvn clean compile} and {@code mvn exec:java} commands in the module root folder.</p>
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestDataGeneratorApp {
+
+ /** change the value to true to generate also 1GB files; can be time consuming and takes additional 3GB of disk
+ * space (1GB json, 1GB xml and 1GB text) */
+ private static final boolean GENERATE_ALSO_GIGABYTE_DATASETS = false;
+
+ /** path where the generated files should be stored, including the final slash */
+ private static final String FILE_PATH = "";
+
+ /** specifies how the outputs generated from one bean should be separated from each other in the output files */
+ public static final String ENTITY_SEPARATOR = "\n\n";
+
+ private static final Logger LOG = Logger.getLogger(TestDataGeneratorApp.class.getName());
+ private static final URI BASE_URI = URI.create("http://localhost:8080/");
+ private static URI baseUri;
+
+ public static void main(final String[] args) throws Exception {
+ baseUri = args.length > 0 ? URI.create(args[0]) : BASE_URI;
+ final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, createApp());
+
+ LOG.info("Jersey performance test data generation - application started.");
+
+ try {
+ // generate text files - 1kb, 5kb, 10kb, 1MB and optionally 1GB
+ generateFile("simple/text", 1024, FILE_PATH + "custom-1kb.text");
+ generateFile("simple/text", 5 * 1024, FILE_PATH + "custom-5kb.text");
+ generateFile("simple/text", 10 * 1024, FILE_PATH + "custom-10kb.text");
+ generateFile("simple/text", 1024 * 1024, FILE_PATH + "custom-1MB.text");
+ if (GENERATE_ALSO_GIGABYTE_DATASETS) {
+ generateFile("text", 1024 * 1024 * 1024, FILE_PATH + "custom-1GB.text");
+ }
+
+ // generate json files - 1kb, 5kb, 10kb, 1MB and optionally 1GB
+ generateFile("simple/json", 1024, FILE_PATH + "custom-1kb.json");
+ generateFile("simple/json", 5 * 1024, FILE_PATH + "custom-5kb.json");
+ generateFile("simple/json", 10 * 1024, FILE_PATH + "custom-10kb.json");
+ generateFile("simple/json", 1024 * 1024, FILE_PATH + "custom-1MB.json");
+ if (GENERATE_ALSO_GIGABYTE_DATASETS) {
+ generateFile("simple/json", 1024 * 1024 * 1024, FILE_PATH + "custom-1GB.json");
+ }
+
+ // generate xml files - 1kb, 5kb, 10kb, 1MB and optionally 1GB
+ generateFile("simple/xml", 1024, FILE_PATH + "custom-1kb.xml");
+ generateFile("simple/xml", 5 * 1024, FILE_PATH + "custom-5kb.xml");
+ generateFile("simple/xml", 10 * 1024, FILE_PATH + "custom-10kb.xml");
+ generateFile("simple/xml", 1024 * 1024, FILE_PATH + "custom-1MB.xml");
+ if (GENERATE_ALSO_GIGABYTE_DATASETS) {
+ generateFile("simple/xml", 1024 * 1024 * 1024, FILE_PATH + "custom-1GB.json");
+ }
+ } catch (final IOException e) {
+ LOG.log(Level.SEVERE, "An error occurred during test data generation. ", e);
+ }
+ server.shutdown();
+ }
+
+ public static ResourceConfig createApp() {
+ return new ResourceConfig()
+ .packages("org.glassfish.jersey.tests.performance.tools")
+ .register(createMoxyJsonResolver());
+ }
+
+ public static ContextResolver<MoxyJsonConfig> createMoxyJsonResolver() {
+ final MoxyJsonConfig moxyJsonConfig = new MoxyJsonConfig();
+ final Map<String, String> namespacePrefixMapper = new HashMap<>(1);
+ namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ moxyJsonConfig.setNamespacePrefixMapper(namespacePrefixMapper).setNamespaceSeparator(':');
+ return moxyJsonConfig.resolver();
+ }
+
+ public static void generateFile(final String resourceRelativeUrl, final int minimalSize, final String fileName)
+ throws IOException {
+ LOG.info("Generating file " + fileName);
+ final Client client = ClientBuilder.newClient();
+ final WebTarget target = client.target(baseUri).path("generate").path(resourceRelativeUrl);
+
+ final File file = new File(fileName);
+ final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(file), Charset.forName("UTF-8")));
+
+ int actualSize = 0;
+ while (actualSize < minimalSize) {
+ final String response = target.request().get(String.class);
+ writer.write(response + ENTITY_SEPARATOR);
+ actualSize += response.length();
+ }
+
+ writer.flush();
+ writer.close();
+ }
+
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorResource.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorResource.java
new file mode 100644
index 0000000..19d72b6
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestDataGeneratorResource.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Resource for generating data for performance tests.
+ * For more information, see {@link TestDataGeneratorApp}
+ */
+@Path("generate")
+public class TestDataGeneratorResource {
+
+ private static Logger LOG = Logger.getLogger(TestDataGeneratorResource.class.getName());
+
+ /**
+ * Generates plain text based data from a complex testing bean.
+ * @return result of a call to a {@link Object#toString()} method of the populated bean.
+ */
+ @GET
+ @Path("complex/text")
+ public String generateComplexText() {
+ return getComplexTestBean().toString();
+ }
+
+ /**
+ * Generates json based data from a complex testing bean.
+ * @return the bean to be converted to json
+ */
+ @GET
+ @Path("complex/json")
+ @Produces(MediaType.APPLICATION_JSON)
+ public TestBean generateComplexJson() {
+ return getComplexTestBean();
+ }
+
+ /**
+ * Generates xml based data from a complex testing bean.
+ * @return the bean to be converted to xml
+ */
+ @GET
+ @Path("complex/xml")
+ @Produces(MediaType.APPLICATION_XML)
+ public TestBean generateComplexXml() {
+ return getComplexTestBean();
+ }
+
+ /**
+ * Generates plain text based data from a simple testing bean.
+ * @return result of a call to a {@link Object#toString()} method of the populated bean.
+ */
+ @GET
+ @Path("simple/text")
+ public String generateSimpleText() {
+ return getSimpleTestBean().toString();
+ }
+
+ /**
+ * Generates json based data from a simple testing bean.
+ * @return the bean to be converted to json
+ */
+ @GET
+ @Path("simple/json")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Person generateSimpleJson() {
+ return getSimpleTestBean();
+ }
+
+ /**
+ * Generates xml based data from a simple testing bean.
+ * @return the bean to be converted to xml
+ */
+ @GET
+ @Path("simple/xml")
+ @Produces(MediaType.APPLICATION_XML)
+ public Person generateSimpleXml() {
+ return getSimpleTestBean();
+ }
+
+ private TestBean getComplexTestBean() {
+ TestBean bean = new TestBean();
+ try {
+ TestDataGenerator.populateBeanByAnnotations(bean);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error while populating the testing bean.", e);
+ }
+ return bean;
+ }
+
+ private Person getSimpleTestBean() {
+ Person bean = new Person();
+ try {
+ TestDataGenerator.populateBeanByAnnotations(bean);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error while populating the testing bean.", e);
+ }
+ return bean;
+ }
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGenerator.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGenerator.java
new file mode 100644
index 0000000..779acfb
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGenerator.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Abstract class for test data generation.
+ *
+ * <p>Creates the pattern for different generation strategies.
+ * Contains the (limited) logic for class graph walk-through.<p/>
+ * <p>Every field which should be populated must be annotated by
+ * {@link org.glassfish.jersey.tests.performance.tools.GenerateForTest}</p>
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public abstract class TestValueGenerator {
+
+ private static final int MAX_RECURSION_LEVEL = 5;
+
+ private static final Logger log = Logger.getLogger(TestValueGenerator.class.getName());
+
+ /** returns testing data int value */
+ public abstract int getInt();
+
+ /** returns testing data char value */
+ public abstract char getChar();
+
+ /** returns testing data String value */
+ public abstract String getString();
+
+ /** returns testing data long value */
+ public abstract long getLong();
+
+ /** returns testing data float value */
+ public abstract float getFloat();
+
+ /** returns testing data double value */
+ public abstract double getDouble();
+
+ /** returns testing data byte value */
+ public abstract byte getByte();
+
+ /** returns testing data short value */
+ public abstract short getShort();
+
+ /** returns testing data boolean value */
+ public abstract boolean getBoolean();
+
+ /** returns testing data enum value */
+ public abstract <T> T getEnum(Class<T> enumType);
+
+ protected Object handlePrimitivesAndWrappers(Class<?> type) {
+ if (type.isAssignableFrom(String.class)) {
+ return getString();
+ }
+ if (type.isAssignableFrom(Integer.class) || type.isAssignableFrom(int.class)) {
+ return getInt();
+ }
+ if (type.isAssignableFrom(Character.class) || type.isAssignableFrom(char.class)) {
+ return getChar();
+ }
+ if (type.isAssignableFrom(Float.class) || type.isAssignableFrom(float.class)) {
+ return getFloat();
+ }
+ if (type.isAssignableFrom(Long.class) || type.isAssignableFrom(long.class)) {
+ return getLong();
+ }
+ if (type.isAssignableFrom(Double.class) || type.isAssignableFrom(double.class)) {
+ return getDouble();
+ }
+ if (type.isAssignableFrom(Byte.class) || type.isAssignableFrom(byte.class)) {
+ return getByte();
+ }
+ if (type.isAssignableFrom(Short.class) || type.isAssignableFrom(short.class)) {
+ return getShort();
+ }
+ if (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class)) {
+ return getBoolean();
+ }
+ return null;
+ }
+
+ protected Object handleCollections(Class<?> type,
+ GenerateForTest annotation,
+ int recursionLevel) throws ReflectiveOperationException {
+ int testDataLength = annotation.length();
+ Class<?> collectionMemberType = annotation.collectionMemberType();
+ Class<?> collectionType = type;
+ if (collectionType.isInterface()) {
+ collectionType = annotation.implementingClass();
+ if (collectionType.equals(Object.class)) {
+ throw new IllegalArgumentException("Unable to instantiate collection - interface was used for the "
+ + "declaration and parameter 'implementingClass' not set.");
+ }
+ }
+ Object collection = collectionType.newInstance();
+ for (int i = 0; i < testDataLength; i++) {
+ // recursively resolve value for collection members
+ Object o = getValueForType(collectionMemberType, null, recursionLevel + 1);
+ // and add it to the collection instance
+ Method addMethod = type.getDeclaredMethod("add", Object.class);
+ addMethod.invoke(collection, o);
+ }
+ return collection;
+ }
+
+ protected Object handleArrays(Class<?> type, GenerateForTest annotation, int recursionLevel)
+ throws ReflectiveOperationException {
+
+ int testDataLength = annotation.length();
+ Class<?> arrayMemberType = type.getComponentType();
+ Object array = Array.newInstance(arrayMemberType, testDataLength);
+ for (int i = 0; i < testDataLength; i++) {
+ Object o = getValueForType(arrayMemberType, null, recursionLevel + 1);
+ Array.set(array, i, o);
+ }
+ return array;
+ }
+
+ public Object getValueForType(Class<?> type, GenerateForTest annotation) throws ReflectiveOperationException {
+ return getValueForType(type, annotation, 0);
+ }
+
+ protected Object getValueForType(Class<?> type, GenerateForTest annotation, int recursionLevel)
+ throws ReflectiveOperationException {
+
+ // handle primitives and wrapper classes
+ Object primitiveOrWrapper = handlePrimitivesAndWrappers(type);
+ if (primitiveOrWrapper != null) {
+ return primitiveOrWrapper;
+ }
+
+ // Handle collections
+ if (Collection.class.isAssignableFrom(type)) {
+ if (annotation != null) {
+ return handleCollections(type, annotation, recursionLevel);
+ } else {
+ return null;
+ }
+ }
+
+ // handle maps (unsupported)
+ if (Map.class.isAssignableFrom(type)) {
+ throw new IllegalArgumentException("Maps are not supported.");
+ }
+
+ // handle enums
+ if (type.isEnum()) {
+ return getEnum(type);
+ }
+
+ // handle arrays
+ if (type.isArray()) {
+ if (annotation != null) {
+ return handleArrays(type, annotation, recursionLevel);
+ } else {
+ return null;
+ }
+ }
+
+ // after selecting-out "all" the other possibilities, we are probably handling a custom inner-bean
+ // create the inner type
+ if (recursionLevel == MAX_RECURSION_LEVEL) {
+ log.fine("Maximum recursion level (" + recursionLevel + ") reached. Ignoring the field.");
+ return null;
+ }
+ Object innerBean = type.newInstance();
+ Field[] fields = type.getDeclaredFields();
+ for (Field field : fields) {
+ GenerateForTest subFieldAnnotation = field.getAnnotation(GenerateForTest.class);
+ if (subFieldAnnotation != null) {
+ field.setAccessible(true);
+ // recursively gather the values for the containing fields and set it
+ field.set(innerBean, getValueForType(field.getType(), subFieldAnnotation, recursionLevel + 1));
+ }
+ }
+ return innerBean;
+ }
+
+}
diff --git a/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGeneratorFactory.java b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGeneratorFactory.java
new file mode 100644
index 0000000..cb268b5
--- /dev/null
+++ b/tests/performance/tools/src/main/java/org/glassfish/jersey/tests/performance/tools/TestValueGeneratorFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.tools;
+
+/**
+ * Factory for {@link org.glassfish.jersey.tests.performance.tools.TestValueGenerator} implementations.
+ *
+ * @author Adam Lindenthal (adam.lindenthal at oracle.com)
+ */
+public class TestValueGeneratorFactory {
+ /**
+ * Returns instance of {@link org.glassfish.jersey.tests.performance.tools.TestValueGenerator}
+ * @param strategy data generation strategy
+ * @return generator instance
+ */
+ public static TestValueGenerator getGenerator(TestDataGenerationStrategy strategy) {
+ if (strategy == TestDataGenerationStrategy.CONSTANT) {
+ return new ConstantTestValueGenerator();
+ } else if (strategy == TestDataGenerationStrategy.RANDOM) {
+ return new RandomTestValueGenerator();
+ }
+ throw new IllegalArgumentException("Requested TestDataGenerationStrategy does not exist.");
+ }
+}
diff --git a/tests/pom.xml b/tests/pom.xml
new file mode 100644
index 0000000..9d6e92a
--- /dev/null
+++ b/tests/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <packaging>pom</packaging>
+ <name>jersey-tests</name>
+
+ <description>
+ Test modules containing test scenario types that involve multiple implementation
+ modules (integration, functional, etc. tests).
+ </description>
+
+ <modules>
+ <module>e2e</module>
+ <module>e2e-client</module>
+ <module>e2e-core-common</module>
+ <module>e2e-entity</module>
+ <module>e2e-inject</module>
+ <module>e2e-server</module>
+ <module>e2e-testng</module>
+ <module>integration</module>
+ <module>mem-leaks</module>
+ <module>osgi</module>
+ <module>stress</module>
+ <module>performance</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey</groupId>
+ <artifactId>jersey-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.inject</groupId>
+ <artifactId>jersey-hk2</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <configuration>
+ <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/tests/stress/pom.xml b/tests/stress/pom.xml
new file mode 100644
index 0000000..e9c359c
--- /dev/null
+++ b/tests/stress/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>stress</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-stress</name>
+
+ <description>
+
+ Jersey stress tests
+
+ This module may contain tests which execution is limited by time (or a fault). This may lead to a considerable longer
+ build of Jersey.
+
+ </description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>-Xmx2048m ${surefire.coverage.argline}</argLine>
+ <forkMode>always</forkMode>
+ <enableAssertions>false</enableAssertions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>sonar</id>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- disable JaCoCo listener because it's not working with <forkMode>always</fork> (<reuseForks>false</reuseForks> respectively)
+ https://jira.sonarsource.com/browse/SONARJAVA-728 (https://github.com/SonarSource/sonar-java/pull/324) -->
+ <properties combine.self="override" />
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/stress/src/test/java/org/glassfish/jersey/server/internal/monitoring/MultiThreadingAggregatedReservoirTest.java b/tests/stress/src/test/java/org/glassfish/jersey/server/internal/monitoring/MultiThreadingAggregatedReservoirTest.java
new file mode 100644
index 0000000..95fff83
--- /dev/null
+++ b/tests/stress/src/test/java/org/glassfish/jersey/server/internal/monitoring/MultiThreadingAggregatedReservoirTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server.internal.monitoring;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+
+import org.glassfish.jersey.server.internal.monitoring.core.TimeReservoir;
+import org.glassfish.jersey.server.internal.monitoring.core.UniformTimeSnapshot;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Multi Threading concurrency test of Jersey monitoring internals.
+ *
+ * @author Stepan Vavra (stepan.vavra at oracle.com)
+ */
+public class MultiThreadingAggregatedReservoirTest {
+
+ private static final Logger LOGGER = Logger.getLogger(MultiThreadingAggregatedReservoirTest.class.getName());
+
+ private static final int PRODUCER_COUNT = 5;
+ private static final int CONSUMER_COUNT = 5;
+
+ /**
+ * Note that more than 5 seconds may require more than 1G heap memory.
+ */
+ private static final int TEST_DURATION_MILLIS = 10_000;
+ private static final int SHUTDOWN_TIMEOUT_SECONDS = 120;
+ private static final double DELTA = 0.0001;
+
+ private final AtomicInteger incrementer = new AtomicInteger(0);
+
+ private final ExecutorService producerExecutorService = Executors
+ .newFixedThreadPool(PRODUCER_COUNT, new ThreadFactoryBuilder().setDaemon(true).build());
+
+ private final ExecutorService consumerExecutorService = Executors
+ .newFixedThreadPool(CONSUMER_COUNT, new ThreadFactoryBuilder().setDaemon(true).build());
+
+ private final long startTime = System.nanoTime();
+ private final TimeUnit startUnitTime = TimeUnit.NANOSECONDS;
+
+ private final AggregatingTrimmer trimmer =
+ new AggregatingTrimmer(startTime(), startUnitTime, 10, TimeUnit.MICROSECONDS);
+ private final SlidingWindowTimeReservoir time10usReservoir =
+ new SlidingWindowTimeReservoir(10, TimeUnit.MICROSECONDS,
+ startTime(), startUnitTime, trimmer);
+ private final AggregatedSlidingWindowTimeReservoir time1DayAggregatedReservoir =
+ new AggregatedSlidingWindowTimeReservoir(1,
+ TimeUnit.DAYS,
+ startTime(), startUnitTime, trimmer);
+ private final AggregatedSlidingWindowTimeReservoir time10DaysAggregatedReservoir =
+ new AggregatedSlidingWindowTimeReservoir(
+ 10, TimeUnit.DAYS,
+ startTime(), startUnitTime, trimmer);
+ private final List<AggregatedSlidingWindowTimeReservoir> aggregatedTimeReservoirs =
+ new CopyOnWriteArrayList<>(
+ Arrays.asList(
+ new AggregatedSlidingWindowTimeReservoir(1, TimeUnit.SECONDS, startTime(),
+ startUnitTime, trimmer),
+ time1DayAggregatedReservoir,
+ time10DaysAggregatedReservoir
+ ));
+
+ /**
+ * Determines the start time of the test.
+ *
+ * @return The start time of the test. Must be a constant value.
+ */
+ protected long startTime() {
+ return startTime;
+ }
+
+ private volatile boolean doShutdown = false;
+
+ /**
+ * Runs {@link #PRODUCER_COUNT} producers that update {@link #time10usReservoir} 10 microseconds sliding window reservoir with
+ * sequentially increasing values generated by {@link @incrementer}. This sliding window updates 1 day aggregated sliding
+ * window and also 10 days aggregated sliding window ({@link #time1DayAggregatedReservoir} and {@link
+ * #time10DaysAggregatedReservoir} respectively). In the meantime, {@link #CONSUMER_COUNT} consumers retrieve snapshots from
+ * the aggregated window in order to increase the level of concurrency.
+ *
+ * @throws InterruptedException If any of the thread was interrupted and the test result won't be reliable
+ */
+ @Test
+ public void parallelProducersAndConsumersTestingAggregatedSlidingWindows() throws InterruptedException {
+
+ executeInParallel(consumerExecutorService, CONSUMER_COUNT, new Runnable() {
+ @Override
+ public void run() {
+ try {
+ LOGGER.info("Consumer starting.");
+ while (!doShutdown && !Thread.currentThread().isInterrupted()) {
+
+ aggregatedTimeReservoirs.get(ThreadLocalRandom.current().nextInt(aggregatedTimeReservoirs.size()))
+ .getSnapshot(System.nanoTime(), TimeUnit.NANOSECONDS);
+ Thread.sleep(100);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ LOGGER.info("Consumer terminating.");
+ }
+ }
+ });
+
+ executeInParallel(producerExecutorService, PRODUCER_COUNT, new Runnable() {
+ @Override
+ public void run() {
+ LOGGER.info("Producer starting.");
+ while (!doShutdown) {
+ final int value = incrementer.incrementAndGet();
+ time10usReservoir.update((long) value, System.nanoTime(), TimeUnit.NANOSECONDS);
+ }
+ LOGGER.info("Producer terminating.");
+ }
+ });
+
+ Thread.sleep(TEST_DURATION_MILLIS);
+ LOGGER.info("Shutting down...");
+
+ doShutdown = true;
+ producerExecutorService.shutdown();
+ consumerExecutorService.shutdown();
+ Assert.assertTrue("Consumer tasks didn't terminated peacefully, aborting this test.",
+ consumerExecutorService.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS));
+ Assert.assertTrue("Producer tasks didn't terminated peacefully, aborting this test.",
+ producerExecutorService.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS));
+
+ final long snapshotTime = System.nanoTime();
+ final long sum = (long) incrementer.get() * (incrementer.get() + 1) / 2;
+
+ LOGGER.info("Integer reached: " + incrementer.get());
+
+ checkInNanos(time1DayAggregatedReservoir, snapshotTime, incrementer.get(), 1, incrementer.get(),
+ (double) sum / incrementer.get(), snapshotTime - startTime());
+ checkInNanos(time10DaysAggregatedReservoir, snapshotTime, incrementer.get(), 1, incrementer.get(),
+ (double) sum / incrementer.get(), snapshotTime - startTime());
+ }
+
+ private void executeInParallel(final Executor consumerExecutorService, final int count, final Runnable runnable) {
+ for (int i = 0; i < count; ++i) {
+ consumerExecutorService.execute(runnable);
+ }
+ }
+
+ /**
+ * Shutdown the producer executor service.
+ */
+ @After
+ public void shutdownProducers() {
+ producerExecutorService.shutdownNow();
+ }
+
+ /**
+ * Shutdown the consumer executor service.
+ */
+ @After
+ public void shutdownConsumers() {
+ consumerExecutorService.shutdownNow();
+ }
+
+ /**
+ * Checks whether the snapshot of given reservoir exhibits with expected measurements.
+ *
+ * @param reservoir The reservoir to assert.
+ * @param snapshotTime The time for which to get the snapshot
+ * @param expectedSize Expected size of the snapshot
+ * @param expectedMin Expected minimum
+ * @param expectedMax Expected maximum
+ * @param expectedMean Expected mean
+ * @param expectedInterval Expected interval
+ */
+ private static void checkInNanos(final TimeReservoir reservoir,
+ final long snapshotTime,
+ final long expectedSize,
+ final long expectedMin,
+ final long expectedMax,
+ final double expectedMean, final long expectedInterval) {
+ final UniformTimeSnapshot snapshot = reservoir.getSnapshot(snapshotTime, TimeUnit.NANOSECONDS);
+
+ assertEquals("Total count does not match!", expectedSize, snapshot.size());
+ assertEquals("Min exec time does not match!", expectedMin, snapshot.getMin());
+ assertEquals("Max exec time does not match!", expectedMax, snapshot.getMax());
+ assertEquals("Average exec time does not match!", expectedMean, snapshot.getMean(), DELTA);
+ assertEquals("Expected interval does not match!", expectedInterval, snapshot.getTimeInterval(TimeUnit.NANOSECONDS));
+ }
+}