diff --git a/containers/jersey-servlet/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java b/containers/jersey-servlet/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java index 5341af30ec..710fc4bfe8 100644 --- a/containers/jersey-servlet/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java +++ b/containers/jersey-servlet/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -128,12 +128,15 @@ public void onStartup(Set> classes, final ServletContext servletContext } private void onStartupImpl(final Set> classes, final ServletContext servletContext) throws ServletException { + final Set registrationsWithApplication = new HashSet<>(); + // first see if there are any application classes in the web app for (final Class applicationClass : getApplicationClasses(classes)) { final ServletRegistration servletRegistration = servletContext.getServletRegistration(applicationClass.getName()); if (servletRegistration != null) { addServletWithExistingRegistration(servletContext, servletRegistration, applicationClass, classes); + registrationsWithApplication.add(servletRegistration); } else { // Servlet is not registered with app name or the app name is used to register a different servlet // check if some servlet defines the app in init params @@ -145,17 +148,21 @@ private void onStartupImpl(final Set> classes, final ServletContext ser if (sr instanceof ServletRegistration) { addServletWithExistingRegistration(servletContext, (ServletRegistration) sr, applicationClass, classes); + registrationsWithApplication.add((ServletRegistration) sr); } } } else { // app not handled by any servlet/filter -> add it - addServletWithApplication(servletContext, applicationClass, classes); + final ServletRegistration sr = addServletWithApplication(servletContext, applicationClass, classes); + if (sr != null) { + registrationsWithApplication.add(sr); + } } } } // check for javax.ws.rs.core.Application registration - addServletWithDefaultConfiguration(servletContext, classes); + addServletWithDefaultConfiguration(servletContext, registrationsWithApplication, classes); } /** @@ -211,12 +218,14 @@ private static void collectJaxRsRegistrations(final Map registrationsWithApplication, final Set> classes) throws ServletException { ServletRegistration registration = context.getServletRegistration(Application.class.getName()); + final Set> appClasses = getRootResourceAndProviderClasses(classes); + if (registration != null) { - final Set> appClasses = getRootResourceAndProviderClasses(classes); final ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(ResourceConfig.class, appClasses) .addProperties(getInitParams(registration)) .addProperties(Utils.getContextParams(context)); @@ -239,13 +248,26 @@ private static void addServletWithDefaultConfiguration(final ServletContext cont } } } + + // make org.glassfish.jersey.servlet.ServletContainer without init params + // work the same as javax.ws.rs.Application + for (ServletRegistration servletRegistration : context.getServletRegistrations().values()) { + if (isJerseyServlet(servletRegistration.getClassName()) + && servletRegistration != registration + && !registrationsWithApplication.contains(servletRegistration) + && getInitParams(servletRegistration).isEmpty()) { + final ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(ResourceConfig.class, appClasses) + .addProperties(Utils.getContextParams(context)); + Utils.store(resourceConfig, context, servletRegistration.getName()); + } + } } /** * Add new servlet according to {@link Application} subclass with {@link ApplicationPath} annotation or existing * {@code servlet-mapping}. */ - private static void addServletWithApplication(final ServletContext context, + private static ServletRegistration addServletWithApplication(final ServletContext context, final Class clazz, final Set> defaultClasses) throws ServletException { final ApplicationPath ap = clazz.getAnnotation(ApplicationPath.class); @@ -266,7 +288,9 @@ private static void addServletWithApplication(final ServletContext context, } else { LOGGER.log(Level.WARNING, LocalizationMessages.JERSEY_APP_MAPPING_CONFLICT(clazz.getName(), mapping)); } + return dsr; } + return null; } /** diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml index b4ca6b9b93..0705923b73 100644 --- a/tests/integration/pom.xml +++ b/tests/integration/pom.xml @@ -122,6 +122,7 @@ servlet-3-init-6 servlet-3-init-7 servlet-3-init-8 + servlet-3-init-9 servlet-3-init-provider servlet-3-params servlet-3-sse-1 diff --git a/tests/integration/servlet-3-init-9/pom.xml b/tests/integration/servlet-3-init-9/pom.xml new file mode 100644 index 0000000000..0f19b4accf --- /dev/null +++ b/tests/integration/servlet-3-init-9/pom.xml @@ -0,0 +1,72 @@ + + + + + 4.0.0 + + + org.glassfish.jersey.tests.integration + project + 2.33-SNAPSHOT + + + servlet-3-init-9 + war + jersey-tests-integration-servlet-3-init-9 + + Servlet integration test - servlet-3-init-9 - no Application subclass is present; + dynamically add a servlet for class-name=org.glassfish.jersey.servlet.ServletContainer + servlet-mapping in web.xml + + + + org.glassfish.jersey.containers + jersey-container-servlet + + + javax.servlet + javax.servlet-api + ${servlet3.version} + provided + + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-external + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.mortbay.jetty + jetty-maven-plugin + + + + diff --git a/tests/integration/servlet-3-init-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResource.java b/tests/integration/servlet-3-init-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResource.java new file mode 100644 index 0000000000..b1967006ac --- /dev/null +++ b/tests/integration/servlet-3-init-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResource.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/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_9; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +@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-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWriter.java b/tests/integration/servlet-3-init-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWriter.java new file mode 100644 index 0000000000..193ce928c9 --- /dev/null +++ b/tests/integration/servlet-3-init-9/src/main/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWriter.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/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_9; + +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; + +@Provider +public class HelloWriter implements MessageBodyWriter { + + @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 httpHeaders, + final OutputStream entityStream) throws IOException, WebApplicationException { + entityStream.write(("Hello World! " + this.getClass().getPackage().getName()).getBytes()); + } +} diff --git a/tests/integration/servlet-3-init-9/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-3-init-9/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..8d76de9764 --- /dev/null +++ b/tests/integration/servlet-3-init-9/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + + + + myApplication + org.glassfish.jersey.servlet.ServletContainer + + + myApplication + /a/* + + + + myApplication2 + org.glassfish.jersey.servlet.ServletContainer + + + myApplication2 + /b/* + + diff --git a/tests/integration/servlet-3-init-9/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResourceITCase.java b/tests/integration/servlet-3-init-9/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResourceITCase.java new file mode 100644 index 0000000000..30dadc934a --- /dev/null +++ b/tests/integration/servlet-3-init-9/src/test/java/org/glassfish/jersey/tests/integration/servlet_3_init_9/HelloWorldResourceITCase.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/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_9; + +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; + +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 testHelloWorldA() throws Exception { + String s = target().path("a").path("helloworld").request().get(String.class); + assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName())); + } + + @Test + public void testHelloWorldB() throws Exception { + String s = target().path("b").path("helloworld").request().get(String.class); + assertTrue(s.equals("Hello World! " + this.getClass().getPackage().getName())); + } +}