Skip to content
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

[bravo-0013] Implement new payment API to receive payments by user id #25

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

lystive
Copy link

@lystive lystive commented Mar 17, 2022

Ticket bravo-0013

What was changed:

  1. Added new payments API to retrieve payments by user id
  2. Added new mapstruct dependency, since the existing dependency is useful is some cases
  3. Update pom.xml
  4. Additional fixes
  5. Cover changes by Junit and Integration tests

Why did I decide to use userId as a Request Parameter?

For me it looks weird we would have a path variable, since then the endpoint should look like /users/{userId}/payments.
As was mentioned in the ticket, we need to use PaymentController, so the best practices would be using userId as request param.
Sometimes it depends on what we would have in the future.

Also there was a couple of things:
We could fetch payments by creating new repository interface, as I've done, but on the other hand the implementation could be:

  1. Simply create a new method in UserController with endpoint /users/{userId}/payments
  2. Call user service and fetch user by id
  3. Get List of payments of user if one exists.
  4. But as I said it depends on project needs.

…nal fixes, adding mapstruct to pom, cover by tests
@wheeleruniverse
Copy link
Member

I want to start by saying that we are not expecting any additional commits. Feel free to make them if you wish, but that's not an expectation that we have. With that said I will go through your changes and leave technical comments on them.

<mysql.connector.version>8.0.24</mysql.connector.version>
<orika.core.version>1.5.4</orika.core.version>
<springfox.swagger2.version>2.5.0</springfox.swagger2.version>
<springfox.swagger.ui.version>2.5.0</springfox.swagger.ui.version>
Copy link
Member

Choose a reason for hiding this comment

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

Nice clean up here.

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorDto handlePaymentNotFoundException(final PaymentNotFoundException exception){
log.info("Payments not found, details: {}", exception.getMessage());
var errorDto = new ErrorDto();
Copy link
Member

Choose a reason for hiding this comment

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

errorDto could be final

Copy link
Author

Choose a reason for hiding this comment

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

Agree, thanks

import org.mapstruct.Mapping;
import org.mapstruct.Named;

@Mapper(componentModel = "spring")
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain what componentModel = "spring" means?

Copy link
Author

Choose a reason for hiding this comment

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

@wheelerswebservices it means construct mapper as spring bean. Because mapper has different construction types, using factory, spring beans etc.

return payments.stream().map(this::convertPayment).collect(Collectors.toList());
}

public PaymentDto convertPayment(final Payment payment){
Copy link
Member

Choose a reason for hiding this comment

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

Can you elaborate on why the new PaymentMapper class is superior to these methods within the existing ResourceMapper class?

Copy link
Author

Choose a reason for hiding this comment

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

@wheelerswebservices because mapperFacade, which is used here is not the flexible one from SOLID principles perpective.
First of all, if you would have 10 dto's which you need to map from the entity its not a good idea to create 20 methods inside ResourseMapper class.
Second, is that you need to implement all of the extra mapping, or when field names are different. In the Mapstruct its simple, you only need an interface, and specify everything only using annotations. Its very useful and simple to understand. Its flexible when you need some extra mappings, for example as was for card mask. So everything for this mapping is located only in 1 Java interface.
Thats why mapstruct is so popular today.
You could read all the details below: https://www.baeldung.com/java-performance-mapping-frameworks

private static final String MESSAGE = "Payment not found for user with id {0}";

public PaymentNotFoundException(String userId) {
super(MessageFormat.format(MESSAGE, userId));
Copy link
Member

Choose a reason for hiding this comment

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

  1. Why did you use MessageFormat.format instead of String.format?
  2. Do you think this MESSAGE variable is really necessary as it's only used in 1 place?

Copy link
Author

Choose a reason for hiding this comment

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

@wheelerswebservices regarding first: I don't think this is really matters
second: this exception is only related to Payment not found flow, so there is not reason to extract this message somewhere else.


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PaymentDto {
Copy link
Member

Choose a reason for hiding this comment

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

Why annotate with Builder, AllArgsConstructor, and NoArgsConstructor if they are not all being used?

Copy link
Author

Choose a reason for hiding this comment

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

Builder used to simplify construction for testing. Since we use Builder, NoArgs and AllArgs constrcustors is required for MapStruct.

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.

3 participants