Alex_Pap
Alex_Pap

Reputation: 464

How to Solve Law of Demeter Violation in Java Records?

I am using the below record in my Quarkus application and at some point I need to access the requestId field, located in Statements nested record. I want to avoid using the getters provided by the nested records since this will invoke a Law of Demeter violation. I tried to add a fifth field named Statements in KYAAutoResponse record and then use a custom method to gain access to requestId automatically but this returns null.

I am a little confused on how could I bypass the violation. Can you help me?

public record KYAAutoResponse(
        DataTransFlowAccessOutputRecord dataTransFlowAccessOutputRecord
) {
    public record DataTransFlowAccessOutputRecord(
            Data data
    ) {
        public record Data(
                Document document
        ) {
            public record Document(
                    Statements statements
            ) {
                @JsonInclude(JsonInclude.Include.NON_NULL)
                public record Statements(
                        @JsonProperty("request-id") String requestId
                ) {}
            }
        }
    }
}

Upvotes: 0

Views: 87

Answers (2)

Alex_Pap
Alex_Pap

Reputation: 464

I made the decision to follow the below approach which I think it's the closest in solving my problem. I placed methods in each of the nested records that call the next one. This means that KYAAutoResponse object knows the internals of DataTransFlowAccessOutputRecord etc.

public record GovResponse(
        DataTransFlowAccessOutputRecord dataTransFlowAccessOutputRecord
) {

    public String getRequestId() {
        return dataTransFlowAccessOutputRecord.getRequestId();
    }

    public record DataTransFlowAccessOutputRecord(
            Data data
    ) {

        public String getRequestId() {
            return data.getRequestId();
        }

        public record Data(
                Document document
        ) {

            public String getRequestId() {
                return document.getRequestId();
            }

            public record Document(
                    Statements statements
            ) {

                public String getRequestId() {
                    return statements.requestId;
                }

                @JsonbNillable
                public record Statements(
                        @JsonbProperty("request-id") String requestId
                ) {}
            }
        }
    }
}

Upvotes: 0

Nick Holt
Nick Holt

Reputation: 34321

If I understand correctly, you want to be able to do kyaAutoResponse.requestId().

This will allow you to do this:

public record KYAAutoResponse(
    DataTransFlowAccessOutputRecord dataTransFlowAccessOutputRecord,
    long callSequenceId,
    String callSequenceDate
) {
    public record DataTransFlowAccessOutputRecord(
        Data data
    ) {
        public record Data(
            Document document
        ) {
            public record Document(
                Statements statements
            ) {
                @JsonInclude(JsonInclude.Include.NON_NULL)
                public record Statements(
                    @JsonProperty("request-id") String requestId,
                    @JsonProperty("consent_content") String data
                ) {}
            }
        }
    }

    @JsonIgnore
    public Optional<String> requestId() {
        if (dataTransFlowAccessOutputRecord == null) return Optional.empty();
        if (dataTransFlowAccessOutputRecord.data == null) return Optional.empty();
        if (dataTransFlowAccessOutputRecord.data.document == null) return Optional.empty();
        if (dataTransFlowAccessOutputRecord.data.document.statements == null) return Optional.empty();
        return Optional.ofNullable(dataTransFlowAccessOutputRecord.data.document.statements.requestId);
    }
}

Upvotes: 1

Related Questions