GH-1034 Finish merging work to support web workloads in serverless environments

Resolves #1034
This commit is contained in:
Oleg Zhurakousky
2023-05-09 12:10:47 +02:00
parent e7e808916b
commit 74aaadea98
31 changed files with 187 additions and 742 deletions

View File

@@ -9,13 +9,12 @@
<description>Base serverless web adapter</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-parent</artifactId>
<version>3.2.10-SNAPSHOT</version>
<artifactId>spring-cloud-function-parent</artifactId>
<version>4.0.3-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
@@ -25,12 +24,12 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<!-- <version>6.0.8</version> -->
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<!-- <version>6.0.0</version>-->
<!-- <scope>provided</scope>-->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -21,9 +21,9 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2023-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.function.serverless.web;
import java.util.Collection;
@@ -5,10 +21,16 @@ import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterRegistration;
/**
*
* @author Oleg Zhurakousky
* @since 4.x
*
*/
public class ProxyFilterRegistration implements FilterRegistration, FilterRegistration.Dynamic {
public Filter getFilter() {

View File

@@ -42,21 +42,22 @@ import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ReadListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.ReadListener;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConnection;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpUpgradeHandler;
import jakarta.servlet.http.Part;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
@@ -589,12 +590,6 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
throw new UnsupportedOperationException();
}
@Override
@Deprecated
public String getRealPath(String path) {
return this.servletContext.getRealPath(path);
}
public void setRemotePort(int remotePort) {
throw new UnsupportedOperationException();
}
@@ -674,7 +669,7 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
}
@Override
public javax.servlet.DispatcherType getDispatcherType() {
public DispatcherType getDispatcherType() {
return this.dispatcherType;
}
@@ -814,7 +809,8 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
@Override
@Nullable
public String getPathTranslated() {
return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
//return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
return this.pathInfo;
}
public void setContextPath(String contextPath) {
@@ -947,12 +943,6 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
return this.requestedSessionIdFromURL;
}
@Override
@Deprecated
public boolean isRequestedSessionIdFromUrl() {
return isRequestedSessionIdFromURL();
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
throw new UnsupportedOperationException();
@@ -981,7 +971,7 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
}
@Override
public Collection<javax.servlet.http.Part> getParts() throws IOException, ServletException {
public Collection<Part> getParts() throws IOException, ServletException {
List<Part> result = new LinkedList<>();
for (List<Part> list : this.parts.values()) {
result.addAll(list);
@@ -993,4 +983,22 @@ public class ProxyHttpServletRequest implements HttpServletRequest {
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
throw new UnsupportedOperationException();
}
@Override
public String getRequestId() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getProtocolRequestId() {
// TODO Auto-generated method stub
return null;
}
@Override
public ServletConnection getServletConnection() {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -29,10 +29,10 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
@@ -42,6 +42,7 @@ import org.springframework.web.util.WebUtils;
/**
*
* @author Oleg Zhurakousky
* @since 4.x
*
*/
public class ProxyHttpServletResponse implements HttpServletResponse {
@@ -295,18 +296,6 @@ public class ProxyHttpServletResponse implements HttpServletResponse {
return encodeURL(url);
}
@Override
@Deprecated
public String encodeUrl(String url) {
return encodeURL(url);
}
@Override
@Deprecated
public String encodeRedirectUrl(String url) {
return encodeRedirectURL(url);
}
@Override
public void sendError(int status, String errorMessage) throws IOException {
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
@@ -379,11 +368,6 @@ public class ProxyHttpServletResponse implements HttpServletResponse {
}
}
@Override
@Deprecated
public void setStatus(int status, String errorMessage) {
throw new UnsupportedOperationException();
}
@Override
public int getStatus() {

View File

@@ -25,22 +25,22 @@ import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
@@ -169,7 +169,7 @@ public class ProxyMvc {
*/
ProxyFilterChain(DispatcherServlet servlet) {
List<Filter> filters = new ArrayList<>();
servlet.getServletContext().getFilterRegistrations().values().forEach(fr -> filters.add(((ProxyFilterRegistration)fr).getFilter()));
servlet.getServletContext().getFilterRegistrations().values().forEach(fr -> filters.add(((ProxyFilterRegistration) fr).getFilter()));
Assert.notNull(filters, "filters cannot be null");
Assert.noNullElements(filters, "filters cannot contain null values");
this.filters = initFilterList(servlet, filters.toArray(new Filter[] {}));

View File

@@ -20,29 +20,25 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterRegistration;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.ServletRegistration.Dynamic;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.SessionTrackingMode;
import jakarta.servlet.descriptor.JspConfigDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -130,31 +126,11 @@ public class ProxyServletContext implements ServletContext {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public Servlet getServlet(String name) throws ServletException {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public Enumeration<Servlet> getServlets() {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public Enumeration<String> getServletNames() {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public void log(String msg) {
this.logger.info(msg);
}
@Override
public void log(Exception exception, String msg) {
this.logger.error(msg, exception);
}
@Override
public void log(String message, Throwable throwable) {
this.logger.error(message, throwable);
@@ -241,25 +217,26 @@ public class ProxyServletContext implements ServletContext {
}
@Override
public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className) {
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
Map<String, FilterRegistration> filterRegistrations = new HashMap<>();
@Override
public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
try {
Filter filter = filterClass.getDeclaredConstructor().newInstance();
ProxyFilterRegistration registration = new ProxyFilterRegistration(filterName, filter);
filterRegistrations.put(filterName, registration);
return registration;
} catch (Exception e) {
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}
@@ -290,12 +267,12 @@ public class ProxyServletContext implements ServletContext {
}
@Override
public Set<javax.servlet.SessionTrackingMode> getDefaultSessionTrackingModes() {
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}
@Override
public Set<javax.servlet.SessionTrackingMode> getEffectiveSessionTrackingModes() {
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
throw new UnsupportedOperationException("This ServletContext does not represent a running web container");
}

View File

@@ -1,15 +1,38 @@
/*
* Copyright 2023-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.function.serverless.web;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletSecurityElement;
import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.ServletSecurityElement;
/**
*
* @author Oleg Zhurakousky
* @since 4.x
*
*/
public class ProxyServletRegistration implements ServletRegistration, ServletRegistration.Dynamic, Comparable<ProxyServletRegistration> {
private final String servletName;

View File

@@ -18,10 +18,9 @@ package org.springframework.cloud.function.serverless.web;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@@ -18,11 +18,11 @@ package org.springframework.cloud.function.test.app;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -32,7 +32,6 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
//@SpringBootApplication
@Configuration
@Import({ PetsController.class })
public class PetStoreSpringAppConfig {

View File

@@ -33,7 +33,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@RestController
@EnableWebMvc
public class PetsController {
@RequestMapping(path = "/pets", method = RequestMethod.POST)
@RequestMapping(path = "/pets/", method = RequestMethod.POST)
public Pet createPet(@RequestBody Pet newPet) {
if (newPet.getName() == null || newPet.getBreed() == null) {
return null;