Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1972cb5
Replace servlet context logging with JUL logging in com.google.gwt.us…
g-keiser Jun 27, 2025
7593341
Add RPC logging facade backed by service loader
g-keiser Sep 25, 2025
752da22
Add ServletContext parameter to RpcLogger methods, allow only one ini…
g-keiser Dec 10, 2025
8479994
Remove unneeded double-checked locking from RpcLogManager#getLoggerPr…
g-keiser Dec 11, 2025
a193b4b
Added missing prefix to ServletContextLogger#error(String, Throwable,…
g-keiser Dec 11, 2025
ff5c4a4
Remove reflective logger implementations
g-keiser Feb 11, 2026
4c02c1d
Remove accidentally committed logging
g-keiser Feb 11, 2026
aed9365
Add real delegate to RpcLogger constructor instead of trying to lazil…
g-keiser Feb 11, 2026
370a386
Remove manual logger initialization mechanisms
g-keiser Feb 12, 2026
6c56728
Remove redundant atomic for RpcLoggerProvider
g-keiser Feb 12, 2026
949f5ef
Fix link to maven guide
g-keiser Feb 12, 2026
fc0680f
Remove RpcLoggerProvider services file, which is not being packaged p…
g-keiser Feb 12, 2026
68a3b9d
Remove reference to services directory from maven build script
g-keiser Feb 12, 2026
5dd9a4f
Correct continuation indent
g-keiser Feb 12, 2026
72127bc
Remove ServletContext parameter from RpcLogger methods by instead set…
g-keiser Feb 13, 2026
0d09368
Improve javadoc comment
g-keiser Feb 13, 2026
2091f1c
Update javadoc
g-keiser Feb 13, 2026
fd4e266
Merge initialize and get provider methods in RpcLogManager
g-keiser Feb 25, 2026
ece5acf
Revert changes to RemoteServiceServletTest
g-keiser Feb 25, 2026
cecfc97
Remove unneeded layer of indirection by combining RpcLogger and RpcLo…
g-keiser Apr 27, 2026
a0010c1
Remove unneeded locking from logger provider initialization
g-keiser Apr 27, 2026
219daba
Improve documentation of RPC logging package
g-keiser Apr 27, 2026
19969ef
Correct an inaccurate javadoc
g-keiser Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

`$ ant clean dist`

- To create maven artifacts (after building .jar using ant), use [following guide](./maven/README.txt).
- To create maven artifacts (after building .jar using ant), use [following guide](./maven/README.md).

### How to verify GWT code conventions:

Expand Down
12 changes: 12 additions & 0 deletions user/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,17 @@
</tokenfilter>
</filterchain>
</move>
<move todir="${project.build}/jakarta-src/com/google/gwt/user/server/rpc/logging/jakarta">
<fileset dir="${project.build}/no-servlet-src/com/google/gwt/user/server/rpc/logging">
<include name="**/*.java"/>
</fileset>
<filterchain>
<tokenfilter>
<replacestring from="package com.google.gwt.user.server.rpc.logging" to="package com.google.gwt.user.server.rpc.logging.jakarta"/>
<replacestring from="javax.servlet" to="jakarta.servlet"/>
</tokenfilter>
</filterchain>
</move>
<move todir="${project.build}/jakarta-src/com/google/gwt/user/server/rpc/jakarta">
<filelist dir="${project.build}/no-servlet-src/com/google/gwt/user/server/rpc">
<file name="AbstractRemoteServiceServlet.java"/>
Expand All @@ -178,6 +189,7 @@
<tokenfilter>
<replacestring from="package com.google.gwt.user.server.rpc" to="package com.google.gwt.user.server.rpc.jakarta"/>
<replacestring from="com.google.gwt.user.server.Util" to="com.google.gwt.user.server.jakarta.Util"/>
<replacestring from="com.google.gwt.user.server.rpc.logging" to="com.google.gwt.user.server.rpc.logging.jakarta"/>
<replacestring from="javax.servlet" to="jakarta.servlet"/>
</tokenfilter>
</filterchain>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -41,9 +40,8 @@ public AbstractRemoteServiceServlet() {
* Standard HttpServlet method: handle the POST. Delegates to
* {@link #processPost(HttpServletRequest, HttpServletResponse)}.
*
* This doPost method swallows ALL exceptions, logs them in the
* ServletContext, and returns a GENERIC_FAILURE_MSG response with status code
* 500.
* This doPost method swallows ALL exceptions, logs them,
* and returns a GENERIC_FAILURE_MSG response with status code 500.
*/
@Override
public final void doPost(HttpServletRequest request,
Expand Down Expand Up @@ -106,9 +104,7 @@ protected void doUnexpectedFailure(Throwable e) {
*/
throw new RuntimeException("Unable to report failure", e);
}
ServletContext servletContext = getServletContext();
RPCServletUtils.writeResponseForUnexpectedFailure(servletContext,
getThreadLocalResponse(), e);
RPCServletUtils.writeResponseForUnexpectedFailure(getThreadLocalResponse(), e);
}

/**
Expand Down
49 changes: 36 additions & 13 deletions user/src/com/google/gwt/user/server/rpc/RPCServletUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.google.gwt.user.server.rpc;

import com.google.gwt.user.server.rpc.logging.RpcLogManager;
import com.google.gwt.user.server.rpc.logging.RpcLogger;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -37,6 +39,8 @@
*/
public class RPCServletUtils {

private static final RpcLogger logger = RpcLogManager.getLogger(RPCServletUtils.class);

public static final String CHARSET_UTF8_NAME = "UTF-8";

/**
Expand All @@ -62,9 +66,11 @@ public class RPCServletUtils {

private static final String CONTENT_ENCODING_GZIP = "gzip";

private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8";
private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 =
"application/json; charset=utf-8";

private static final String GENERIC_FAILURE_MSG = "The call failed on the server; see server log for details";
private static final String GENERIC_FAILURE_MSG =
"The call failed on the server; see server log for details";

private static final String GWT_RPC_CONTENT_TYPE = "text/x-gwt-rpc";

Expand Down Expand Up @@ -319,22 +325,30 @@ public static boolean shouldGzipResponseContent(HttpServletRequest request,
&& exceedsUncompressedContentLengthLimit(responseContent);
}

/**
* @deprecated Use {@link #writeResponse(HttpServletResponse, String, boolean)} instead; the
* servlet context is no longer needed.
*/
@Deprecated
public static void writeResponse(ServletContext ignored, HttpServletResponse response,
String responseContent, boolean gzipResponse) throws IOException {
writeResponse(response, responseContent, gzipResponse);
}

/**
* Write the response content into the {@link HttpServletResponse}. If
* <code>gzipResponse</code> is <code>true</code>, the response content will
* be gzipped prior to being written into the response.
*
* @param servletContext servlet context for this response
* @param response response instance
* @param responseContent a string containing the response content
* @param gzipResponse if <code>true</code> the response content will be gzip
* encoded before being written into the response
* @throws IOException if reading, writing, or closing the response's output
* stream fails
*/
public static void writeResponse(ServletContext servletContext,
HttpServletResponse response, String responseContent, boolean gzipResponse)
throws IOException {
public static void writeResponse(HttpServletResponse response, String responseContent,
boolean gzipResponse) throws IOException {

byte[] responseBytes = responseContent.getBytes(StandardCharsets.UTF_8);
if (gzipResponse) {
Expand Down Expand Up @@ -363,7 +377,7 @@ public static void writeResponse(ServletContext servletContext,
}

if (caught != null) {
servletContext.log("Unable to compress response", caught);
logger.error("Unable to compress response", caught);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
Expand All @@ -378,18 +392,26 @@ public static void writeResponse(ServletContext servletContext,
response.getOutputStream().write(responseBytes);
}

/**
* @deprecated Use {@link #writeResponseForUnexpectedFailure(HttpServletResponse, Throwable)}
* instead; the servlet context is no longer needed.
*/
@Deprecated
public static void writeResponseForUnexpectedFailure(ServletContext ignored,
HttpServletResponse response, Throwable failure) {
writeResponseForUnexpectedFailure(response, failure);
}

/**
* Called when the servlet itself has a problem, rather than the invoked
* third-party method. It writes a simple 500 message back to the client.
*
* @param servletContext
* @param response
* @param failure
*/
public static void writeResponseForUnexpectedFailure(
ServletContext servletContext, HttpServletResponse response,
public static void writeResponseForUnexpectedFailure(HttpServletResponse response,
Throwable failure) {
servletContext.log("Exception while dispatching incoming RPC call", failure);
logger.error("Exception while dispatching incoming RPC call", failure);

// Send GENERIC_FAILURE_MSG with 500 status.
//
Expand All @@ -403,7 +425,7 @@ public static void writeResponseForUnexpectedFailure(
response.getWriter().write(GENERIC_FAILURE_MSG);
}
} catch (IOException ex) {
servletContext.log(
logger.error(
"respondWithUnexpectedFailure failed while sending the previous failure to the client",
ex);
}
Expand Down Expand Up @@ -431,7 +453,8 @@ private static void checkCharacterEncodingIgnoreCase(
* properly parsed character encoding string if we decide to make this
* change.
*/
if (characterEncoding.toLowerCase(Locale.ROOT).contains(expectedCharSet.toLowerCase(Locale.ROOT))) {
if (characterEncoding.toLowerCase(Locale.ROOT)
.contains(expectedCharSet.toLowerCase(Locale.ROOT))) {
encodingOkay = true;
}
}
Expand Down
83 changes: 38 additions & 45 deletions user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RpcTokenException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.logging.RpcLogManager;
import com.google.gwt.user.server.rpc.logging.RpcLogger;

import java.io.IOException;
import java.io.InputStream;
Expand All @@ -45,6 +47,8 @@
public class RemoteServiceServlet extends AbstractRemoteServiceServlet
implements SerializationPolicyProvider {

private static final RpcLogger logger = RpcLogManager.getLogger(RemoteServiceServlet.class);

/**
* Loads a serialization policy stored as a servlet resource in the same
* ServletContext as this servlet. Returns null if not found.
Expand All @@ -62,7 +66,7 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet,
modulePath = new URL(moduleBaseURL).getPath();
} catch (MalformedURLException ex) {
// log the information, we will default
servlet.log("Malformed moduleBaseURL: " + moduleBaseURL, ex);
logger.error("Malformed moduleBaseURL: " + moduleBaseURL, ex);
}
}

Expand All @@ -74,19 +78,20 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet,
* this method.
*/
if (modulePath == null || !modulePath.startsWith(contextPath)) {
String message = "ERROR: The module path requested, "
String message = "The module path requested, "
+ modulePath
+ ", is not in the same web application as this servlet, "
+ contextPath
+ ". Your module may not be properly configured or your client and server code maybe out of date.";
servlet.log(message);
+ ". Your module may not be properly configured " +
"or your client and server code maybe out of date.";
logger.error(message);
} else {
// Strip off the context path from the module base URL. It should be a
// strict prefix.
String contextRelativePath = modulePath.substring(contextPath.length());

String serializationPolicyFilePath = SerializationPolicyLoader.getSerializationPolicyFileName(contextRelativePath
+ strongName);
String serializationPolicyFilePath = SerializationPolicyLoader.getSerializationPolicyFileName(
contextRelativePath + strongName);

// Open the RPC resource file and read its contents.
InputStream is = servlet.getServletContext().getResourceAsStream(
Expand All @@ -98,30 +103,30 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet,
null);
if (serializationPolicy.hasClientFields()) {
if (ENABLE_ENHANCED_CLASSES) {
servlet.log("WARNING: Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail on the vulnerability that this presents.");
logger.warn("Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail on the vulnerability that this presents.");
} else {
servlet.log("ERROR: Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. Review build logs to see which classes are affected, or set " +
ENABLE_GWT_ENHANCED_CLASSES_PROPERTY + " to true to allow using this " +
"service. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail.");
logger.error("Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. Review build logs to see which classes are affected, or set " +
ENABLE_GWT_ENHANCED_CLASSES_PROPERTY + " to true to allow using this " +
"service. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail.");
serializationPolicy = null;
}
}
} catch (ParseException e) {
servlet.log("ERROR: Failed to parse the policy file '"
logger.error("Failed to parse the policy file '"
+ serializationPolicyFilePath + "'", e);
} catch (IOException e) {
servlet.log("ERROR: Could not read the policy file '"
logger.error("Could not read the policy file '"
+ serializationPolicyFilePath + "'", e);
}
} else {
String message = "ERROR: The serialization policy file '"
String message = "The serialization policy file '"
+ serializationPolicyFilePath
+ "' was not found; did you forget to include it in this deployment?";
servlet.log(message);
logger.error(message);
}
} finally {
if (is != null) {
Expand All @@ -144,7 +149,8 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet,
* A cache of moduleBaseURL and serialization policy strong name to
* {@link SerializationPolicy}.
*/
private final Map<String, SerializationPolicy> serializationPolicyCache = new HashMap<String, SerializationPolicy>();
private final Map<String, SerializationPolicy> serializationPolicyCache =
new HashMap<String, SerializationPolicy>();

/**
* The implementation of the service.
Expand Down Expand Up @@ -177,11 +183,13 @@ public RemoteServiceServlet(Object delegate) {
}

/**
* Overridden to load the gwt.codeserver.port system property.
* Overridden to load the gwt.codeserver.port system property and initialize the
* {@link RpcLogManager} with a provider name from system properties or the servlet config.
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
RpcLogManager.setServletContext(config.getServletContext());
codeServerPort = getCodeServerPort();
}

Expand Down Expand Up @@ -260,12 +268,12 @@ public final SerializationPolicy getSerializationPolicy(String moduleBaseURL,

if (serializationPolicy == null) {
// Failed to get the requested serialization policy; use the default
log(
"WARNING: Failed to get the SerializationPolicy '"
logger.warn("Failed to get the SerializationPolicy '"
+ strongName
+ "' for module '"
+ moduleBaseURL
+ "'; a legacy, 1.3.3 compatible, serialization policy will be used. You may experience SerializationExceptions as a result.");
+ "'; a legacy, 1.3.3 compatible, serialization policy will be used. " +
"You may experience SerializationExceptions as a result.");
serializationPolicy = RPC.getDefaultSerializationPolicy();
}

Expand Down Expand Up @@ -311,7 +319,7 @@ public String processCall(String payload) throws SerializationException {
try {
rpcRequest = RPC.decodeRequest(payload, delegate.getClass(), this);
} catch (IncompatibleRemoteServiceException ex) {
log(
logger.error(
"An IncompatibleRemoteServiceException was thrown while processing this call.",
ex);
return RPC.encodeResponseForFailedRequest(null, ex);
Expand Down Expand Up @@ -350,23 +358,21 @@ public String processCall(RPCRequest rpcRequest) throws SerializationException {
rpcRequest.getParameters(), rpcRequest.getSerializationPolicy(),
rpcRequest.getFlags());
} catch (IncompatibleRemoteServiceException ex) {
log(
logger.error(
"An IncompatibleRemoteServiceException was thrown while processing this call.",
ex);
return RPC.encodeResponseForFailedRequest(rpcRequest, ex);
} catch (RpcTokenException tokenException) {
log("An RpcTokenException was thrown while processing this call.",
tokenException);
logger.error("An RpcTokenException was thrown while processing this call.");
return RPC.encodeResponseForFailedRequest(rpcRequest, tokenException);
}
}

/**
* Standard HttpServlet method: handle the POST.
*
* This doPost method swallows ALL exceptions, logs them in the
* ServletContext, and returns a GENERIC_FAILURE_MSG response with status code
* 500.
* This doPost method swallows ALL exceptions, logs them,
* and returns a GENERIC_FAILURE_MSG response with status code 500.
*
* @throws ServletException
* @throws SerializationException
Expand Down Expand Up @@ -465,19 +471,7 @@ protected String getCodeServerPolicyUrl(String strongName) {
* no authentication. It should only be used during development.</p>
*/
protected SerializationPolicy loadPolicyFromCodeServer(String url) {
SerializationPolicyClient.Logger adapter = new SerializationPolicyClient.Logger() {

@Override
public void logInfo(String message) {
RemoteServiceServlet.this.log(message);
}

@Override
public void logError(String message, Throwable throwable) {
RemoteServiceServlet.this.log(message, throwable);
}
};
return CODE_SERVER_CLIENT.loadPolicy(url, adapter);
return CODE_SERVER_CLIENT.loadPolicy(url);
}

/**
Expand Down Expand Up @@ -541,7 +535,6 @@ private void writeResponse(HttpServletRequest request,
boolean gzipEncode = RPCServletUtils.acceptsGzipEncoding(request)
&& shouldCompressResponse(request, response, responsePayload);

RPCServletUtils.writeResponse(getServletContext(), response,
responsePayload, gzipEncode);
RPCServletUtils.writeResponse(response, responsePayload, gzipEncode);
}
}
Loading