Skip to content

Move Response extraction logic out of init of DavException #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

ArnyminerZ
Copy link
Member

@ArnyminerZ ArnyminerZ commented Aug 5, 2025

Moved all the code inside of init in DavException to its own function to initialize the contents, decoupling a bit better how the data is instantiated.


Depends on #82

@ArnyminerZ ArnyminerZ linked an issue Aug 5, 2025 that may be closed by this pull request
@ArnyminerZ ArnyminerZ requested a review from Copilot August 5, 2025 09:59
@ArnyminerZ ArnyminerZ self-assigned this Aug 5, 2025
@ArnyminerZ ArnyminerZ added the refactoring Internal improvement of existing functions label Aug 5, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the DavException class by extracting HTTP response processing logic from the constructor into a separate populateHttpResponse method. This improves separation of concerns and makes the exception instantiation more flexible.

Key changes:

  • Extracted HTTP response processing logic from init block into populateHttpResponse method
  • Made DavException constructor no longer accept httpResponse parameter
  • Updated all usage sites to call populateHttpResponse after exception creation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
DavException.kt Removed httpResponse parameter from constructor, moved processing logic to populateHttpResponse method
HttpException.kt Updated constructor to call populateHttpResponse instead of passing response to parent
DavResource.kt Updated exception throwing to use fluent API with populateHttpResponse
DavExceptionTest.kt Updated test to use new fluent API pattern

Copy link
Member

@sunkup sunkup left a comment

Choose a reason for hiding this comment

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

It's bothersome to first create DavException and then populate with HttpResponse afterwards.

Is there a good reason for not adding a static fromResponse(response: HttpResponse) to the companion object of DavException, which would create DavException already populated with the needed properties from the response, like @rfc2822 suggested?

@ArnyminerZ
Copy link
Member Author

ArnyminerZ commented Aug 6, 2025

Is there a good reason for not adding a static fromResponse(response: HttpResponse) to the companion object of DavException, which would create DavException already populated with the needed properties from the response, like @rfc2822 suggested?

Yes, DavException is an open class, and some other exceptions inherit from it, and thus need the constructor. Otherwise I think there's too much code duplication...

The other option is to use reflection or something like that, but I don't love that approach.

@sunkup
Copy link
Member

sunkup commented Aug 6, 2025

Right. I meant this: why don't we make populateHttpResponse private (I would also rename the method to populateWithHttpResponse, as otherwise it sounds like it'd populate the HttpResponse) and just add fromResponse to the companion object for ease of access like this:

fun fromResponse(
    message: String,
    httpResponse: Response?,
    ex: Throwable? = null
): DavException = 
    DavException(message, ex).populateWithHttpResponse(httpResponse)

@rfc2822
Copy link
Member

rfc2822 commented Aug 6, 2025

I also wonder about how a good API would look like for the (discussable) requirements that:

  • there's a DavException that is thrown on failures that are not directly HTTP errors, like when
    • dav4jvm expects a 207 multi-status, but gets something else, or
    • there are too many HTTP redirects (other libraries seem to use ProtocolException for that – it's also an option to reuse existing exceptions, if they match)
    • XML processing errors in WebDAV XML
  • HttpException for HTTP errors.

Both should be able to contain some context of the response body because servers often provide useful information in the response body. For instance, errors are often just 500 Internal Server Error, but the response body could contain more information. This information is shown for instance to DAVx5 users in the debug info screen.

Additionally there's the WebDAV XML error element that should be processed.

The classes probably shouldn't be coupled to a specific HTTP framework too tightly.

So some questions that come to my mind:

  • Which exception classes do we actually need?
  • New ones or can some of them be reused?
  • In which relation to each other are they (should they really be derived)?
  • How do we preserve the body excerpt properly (and without redundant code, i.e. where belongs the processing to and from where should it be called)?

@ArnyminerZ
Copy link
Member Author

@sunkup please take a look and see if you like this more.

@sunkup
Copy link
Member

sunkup commented Aug 7, 2025

@sunkup please take a look and see if you like this more.

mmh, no. Now there is a side effect in the constructor: It executes logic (reading/parsing HTTP body) that can throw exceptions or cause blocking I/O. It makes the constructor "unsafe" and violates the general principle that constructors should be light and free of side effects. It now has more than one responsibility (to simply construct and fill the object) so it violates the single-responsibility principle.

Also it is harder to test/mock now because you need to know which constructor you need to use in order to not invoke the population logic.

Using the factory method (fromResponse in companion object) proposed by @rfc2822 , will ensure cleaner separation of concerns: construction vs. population. It allows the constructor to remain side-effect free and it also improves clarity and intention (i.e., "I'm constructing from a response").

Sure, it's slightly more verbose in usage, but I think that's actually a benefit here.

@ArnyminerZ
Copy link
Member Author

I've tried setting up some kind of templating but it's ugly... I honestly don't like it.

@rfc2822
Copy link
Member

rfc2822 commented Aug 13, 2025

I've tried setting up some kind of templating but it's ugly... I honestly don't like it.

I agree. Replaced by #83, please follow up there.

@rfc2822 rfc2822 closed this Aug 13, 2025
@rfc2822 rfc2822 deleted the 80-davexception-contains-http-response branch August 13, 2025 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactoring Internal improvement of existing functions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DavException contains HTTP response
3 participants