Talent-Catalog / talentcatalog

https://tctalent.org
GNU Affero General Public License v3.0
13 stars 4 forks source link

Refactor DtoBuilder #97

Open sadatmalik opened 1 year ago

sadatmalik commented 1 year ago

As a developer I would like to use Jackson serializers So that I can factor out the DtoBuilder

sadatmalik commented 1 year ago
@RestController()
@RequestMapping("/api/admin/branding")
@Slf4j
@RequiredArgsConstructor
public class BrandingAdminApi {

    private final BrandingService brandingService;

    // skeleton code - final cut would not publish entity
    // will implement and use explicit DTO classes with mappers
    @GetMapping()
    public ResponseEntity<BrandingInfo> getBrandingInfo() {
        BrandingInfo info = brandingService.getBrandingInfo(null);
        return ResponseEntity.ok(info);
    }

}
@Getter
@Setter
@ToString
@Builder
public class BrandingInfo {

    /**
     * Optional landing page associated with branding - eg TBB redirects to
     * https://www.talentbeyondboundaries.org/talentcatalog/.
     * <p/>
     * If no landing page is configured, the default is to automatically go to candidate-portal
     */
    @Nullable
    private String landingPage;

    /**
     * Optional path to logo to display with branding.
     */
    @Nullable
    private String logo;

    /**
     * Partner name associated with branding, if known. Null if unknown.
     */
    @Nullable
    private String partnerName;

    /**
     * Website associated with logo
     */
    @Nullable
    private String websiteUrl;

}
@Service
@RequiredArgsConstructor
public class BrandingServiceImpl implements BrandingService {
    private final PartnerService partnerService;
    private final UserService userService;

    /**
     * Returns the branding information for a partner.
     * </p>
     * If a user is logged-in then get the partner associated with that user otherwise get the partner associated with
     * the specified partner abbreviation.
     * </p>
     * If no partner is found gets the default source partner.
     *
     * @param partnerAbbreviation Optional partner abbreviation
     * @return branding info
     */
    @Override
    @NonNull
    public BrandingInfo getBrandingInfo(@Nullable String partnerAbbreviation) {

        User user = userService.getLoggedInUser();

        Partner partner = user != null
                ? user.getPartner()
                : partnerService.getPartnerFromAbbreviation(partnerAbbreviation);

        if (partner == null) {
            partner = partnerService.getDefaultSourcePartner();
        }

        return extractBrandingInfoFromPartner(partner);
    }

    private @NotNull BrandingInfo extractBrandingInfoFromPartner(@NonNull Partner partner) {
        String landingPage = null;

        if (partner instanceof SourcePartner sourcePartner) {
            landingPage = sourcePartner.getRegistrationLandingPage();
        }

        return BrandingInfo.builder()
                .landingPage(landingPage)
                .logo(partner.getLogo())
                .partnerName(partner.getName())
                .websiteUrl(partner.getWebsiteUrl())
                .build();
    }
}
camerojo commented 1 year ago

See this Slack post - https://refugeejobsmarket.slack.com/archives/C0583HJ9CHM/p1686973934520609

sadatmalik commented 1 year ago

Thanks JC - agree with and have replied to the above post in Slack

camerojo commented 1 year ago

Worth looking at https://www.baeldung.com/spring-data-jpa-projections

Also https://www.baeldung.com/jackson-json-view-annotation and https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

Also - if you are getting exceptions around the JPA Session being closed (fetching lazily loaded attributes), try using Transactional on the controller method as described here https://stackoverflow.com/questions/36583185/spring-data-jpa-could-not-initialize-proxy-no-session-with-methods-marke

I think this may be because the JSON serialization of the return value may be done asynchronously (in a separate thread) by which time the JPA Session will have been closed.

camerojo commented 11 months ago

Another interesting approach using Kotlin (which we can intermix with our standard Java I believe).

See https://medium.com/@filipefox/introduction-8a1145c08d00