Skip to content

HDDS-13258. Refactor HttpServletResponse (Part1 - HddsConfServlet)#9126

Merged
peterxcli merged 42 commits into
apache:masterfrom
unknowntpo:HDDS-13258-refactor-HttpServletResponse
Nov 7, 2025
Merged

HDDS-13258. Refactor HttpServletResponse (Part1 - HddsConfServlet)#9126
peterxcli merged 42 commits into
apache:masterfrom
unknowntpo:HDDS-13258-refactor-HttpServletResponse

Conversation

@unknowntpo
Copy link
Copy Markdown
Contributor

@unknowntpo unknowntpo commented Oct 9, 2025

This PR:

  • Send error response according to specified accept format, e.g. JSON, or XML, if no format is specified, fall back to XML.
  • extract enum ResponseFormat for readability.

What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-13258

How was this patch tested?
UT: TestHddsConfServlet

@unknowntpo unknowntpo changed the title Hdds 13258 refactor http servlet response HDDS-13258. Refactor HttpServletResponse (Part1) Oct 9, 2025
@unknowntpo unknowntpo marked this pull request as ready for review October 9, 2025 03:34
@unknowntpo unknowntpo marked this pull request as draft October 9, 2025 03:35
@unknowntpo unknowntpo changed the title HDDS-13258. Refactor HttpServletResponse (Part1) HDDS-13258. Refactor HttpServletResponse (Part1 - HddsConfServlet) Oct 9, 2025
@unknowntpo unknowntpo marked this pull request as ready for review October 9, 2025 04:17
@unknowntpo
Copy link
Copy Markdown
Contributor Author

@peterxcli Would you like to review this PR ?

@unknowntpo unknowntpo closed this Oct 9, 2025
@unknowntpo unknowntpo reopened this Oct 9, 2025
Copy link
Copy Markdown
Contributor

@adoroszlai adoroszlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @unknowntpo for the patch.

I would prefer ResponseFormat and related static methods to be added/moved outside of HddsConfServlet (and matching new test class).

Comment on lines +100 to +102
private void processCommand(String cmd, ResponseFormat format,
HttpServletRequest request, HttpServletResponse response, Writer out,
String name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please do not format method signature like this. Whenever visibility / return type / method name / other modifiers are changed, we would have to reindent all parameters.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Comment on lines +139 to +225
Writer out) throws IOException {
Writer out) throws IOException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not format method signature like this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Comment on lines 83 to 91
switch (format) {
case JSON:
response.setContentType("application/json; charset=utf-8");
break;
case XML:
default:
response.setContentType("text/xml; charset=utf-8");
break;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest adding getContentType() instance method in ResponseFormat, returning application/json and text/xml for JSON and XML respectively. Then we can change this to:

Suggested change
switch (format) {
case JSON:
response.setContentType("application/json; charset=utf-8");
break;
case XML:
default:
response.setContentType("text/xml; charset=utf-8");
break;
}
response.setContentType(format.getContentType() + "; charset=utf-8");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@adoroszlai adoroszlai requested a review from peterxcli October 9, 2025 08:48
@unknowntpo
Copy link
Copy Markdown
Contributor Author

Thanks @unknowntpo for the patch.

I would prefer ResponseFormat and related static methods to be added/moved outside of HddsConfServlet (and matching new test class).

@adoroszlai Do you want to provide a consistent way to deal with HTTP response for all child class of HTTPServlet ?
We can make a HTTPServletUtils class placed at org.apache.hadoop.hdds.utils. What do you think ?

@adoroszlai
Copy link
Copy Markdown
Contributor

We can make a HTTPServletUtils class placed at org.apache.hadoop.hdds.utils. What do you think ?

Sounds good.

@unknowntpo
Copy link
Copy Markdown
Contributor Author

@adoroszlai Refactoring is done, would you like to review it again ?

@adoroszlai adoroszlai self-requested a review October 19, 2025 16:36
Copy link
Copy Markdown
Contributor

@adoroszlai adoroszlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @unknowntpo for updating the patch, LGTM.


private static void writeXmlError(String errorMessage, Writer out) throws IOException {
try {
DocumentBuilderFactory factory = XMLUtils.newSecureDocumentBuilderFactory();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think DocumentBuilderFactory should be stored for reuse.

Once an application has obtained a reference to a DocumentBuilderFactory it can use the factory to configure and obtain parser instances. doc

Something like:

  private static final CheckedSupplier<DocumentBuilderFactory, ParserConfigurationException> DOCUMENT_BUILDER_FACTORY =
      MemoizedCheckedSupplier.valueOf(XMLUtils::newSecureDocumentBuilderFactory);

and

      DocumentBuilder builder = DOCUMENT_BUILDER_FACTORY.get().newDocumentBuilder();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, fixed.

unknowntpo and others added 4 commits October 21, 2025 07:31
…f/HddsConfServlet.java


fix indent

Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…f/HddsConfServlet.java


fix indent

Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…ls/HttpServletUtils.java


fix indent

Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
…ls/TestHttpServletUtils.java


fix indent

Co-authored-by: Doroszlai, Attila <6454655+adoroszlai@users.noreply.github.com>
@unknowntpo
Copy link
Copy Markdown
Contributor Author

@adoroszlai Sorry, that indentation problem happens again.
Actually, I indent my file using Intellij without additional configuration.
Is there any guideline of indentation in Apache Ozone ?

@adoroszlai
Copy link
Copy Markdown
Contributor

Is there any guideline of indentation in Apache Ozone ?

  • Continuation indent: 4
  • turn off Align when multiline

@adoroszlai
Copy link
Copy Markdown
Contributor

@peterxcli please take a look

Comment on lines +96 to +100
case XML:
default:
writeXmlError(errorMessage, writer);
break;
}
Copy link
Copy Markdown
Member

@peterxcli peterxcli Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto (#9126 (comment))

Suggested change
case XML:
default:
writeXmlError(errorMessage, writer);
break;
}
case XML:
writeXmlError(errorMessage, writer);
break;
default:
throw ....;
}

Copy link
Copy Markdown
Contributor Author

@unknowntpo unknowntpo Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I throw an IOException, whose cause is IllegalArgumentException to denote that it happened during writing response to I/O, and caller passed in illegal arguments.

@chungen0126 chungen0126 requested a review from peterxcli November 7, 2025 03:08
Copy link
Copy Markdown
Contributor

@chungen0126 chungen0126 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @unknowntpo for the patch. Left some comments.

*/
public static ResponseFormat getResponseFormat(HttpServletRequest request) throws IllegalArgumentException {
String format = request.getHeader(HttpHeaders.ACCEPT);
if (format == null) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is to use XML as the fallback when the format is null. For any format other than XML or JSON, we should set it to UNSPECIFIED.

public enum ResponseFormat {
UNSPECIFIED("unspecified"),
JSON("json"),
XML("xml");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we use the MediaType constants (e.g., MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) instead of string literals like "json". This is more precise as it directly uses the values that will be set in the HTTP headers, and it also avoids 'magic strings'.

Copy link
Copy Markdown
Member

@peterxcli peterxcli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks very much for this improvement!

@peterxcli
Copy link
Copy Markdown
Member

lets merge this after green CI!

@peterxcli peterxcli merged commit 2e323b4 into apache:master Nov 7, 2025
83 of 84 checks passed
@peterxcli
Copy link
Copy Markdown
Member

Thanks @unknowntpo for this patch, @adoroszlai and @chungen0126 for reviewing!

Comment on lines +156 to +164
/**
* Functional interface for operations that accept a parameter and may throw exceptions.
*
* @param <T> the type of the input to the operation
*/
@FunctionalInterface
public interface CheckedConsumer<T> {
void accept(T t) throws Exception;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In part 2, I think we should reuse CheckedConsumer from org.apache.ratis.util.function instead of defining new interface.

@peterxcli
Copy link
Copy Markdown
Member

@chungen0126 Sorry I didnt notice that you left some comments

@unknowntpo please address them in the part 2 if you think they make sense to you, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants