I'm working on a backend for a web application in Java (using Spring) und try to use the builder pattern. I have the classes
- Example (as a Data object)
- ExampleDocument (as another Data object)
- ExampleMapper
- ExampleRepository (extends MongoRepository)
- ExampleController(REST)
- ExampleService
Now I have a problem with a function returning an Optional (findById, Mongo-Repo) to my service:
@Service
@RequiredArgsConstructor
public class ExampleService {
private final ExampleMapper exampleMapper;
private final ExampleRepository exampleRepository;
public Example getExample(String exampleId) {
Optional<ExampleDocument> document = exampleRepository.findById(exampleId);
return exampleMapper.mapToDto(document);
}
I want to map the document in my mapper class as I'm used to do it with other documents (without the Optional it looks like this, I took an example from another class:
@Component
public class OtherExampleMapper {
public OtherExample mapToDto(OtherExampleDocument document) {
return OtherExample.builder()
.id(document.getId())
.existingSolutions(document.getExistingSolutions())
...
.build();
}
)
I tried to use ifPresent, but the builderPattern seems not to recognize the expression, since I have a yellow mark on "getId()", telling me "Result of 'PitchEventDocument.getId()' is ignored" and a red mark on ".build()"
@Component
public class PitchEventMapper {
public Example mapToDto(Optional<ExampleDocument> document) {
return Example.builder()
.id(document.ifPresent(id -> document.get().getId())
.build();
}
How can I still use the builder pattern in combination with the Optional?
CodePudding user response:
Your basic problem is that ifPresent
doesn't return a value at all—it's void
. Instead, you want orElse
(since I think you want null
or another default value in that case), and you shouldn't use get
—all the relevant "if" and "or" methods already unwrap the value for you.
Instead:
Example.builder()
.id(document.map(Document::getId).orElse(null))
.build()