0

I was reading this so I could understand better how to deal with asynchronous requests, and even though I understand what he is doing here:

.map(processor::responseToDatabaseEntity) // Create a persistable entity from the response
.map(priceRepository::save)               // Save the entity to the database

I have no idea how these two methods would be implemented. Assuming this very simple code:

public Mono<Response> postMethod(String id, Person json) {
        return webClient.post().uri(id).body(Mono.just(json), Person.class).retrieve().bodyToMono(Response.class);
}

And the Response Class, something like:

public class Response implements Serializable{
    
    private static final long serialVersionUID = -4101206629695985431L;
    
    public String statusCode;
    public Date date;
    public PersonInfo data;

I assume the responseToDatabaseEntity method would be some sort of transformation from the Response to PersonInfoDTO to the database, and the save would insert into it. But how could I implement something like that using Method Reference(::) that would work inside the .map() so I can subscribe() after is what I don't understand.

EDIT: Adding the progress I had but adapting more or less to the example I gave with Person class:

public Mono<Object> postPerson(String id, Person json) {
        return webClient.post().uri(id).body(Mono.just(json), Person.class).retrieve().bodyToMono(Response.class).map( c -> {
            List<PersonDTO> list = new ArrayList<PersonDTO>();
            c.data.getRoles().forEach((r) -> {
                PersonDTO dto = new PersonDTO(c.data.getOof(), "something", c.data.getFoo(), r);
                list.add(dto);
            });
            return list;        
        }).map(personController::savePerson).subscribe(); //what I wanted to do
    }

If I do this:

    });
    return list;        
}).map(l -> {
        l.
    });

l contains a list of PersonDTO, and if I do this:

  .map(l -> {
        l.forEach( f -> {
            f.
        });
    });

f contains a Person.

How should I implement the method to send the entire list to insert in the method or send one person by person to save. I can't use a static method like PersonController::savePerson because:

@RestController
public class PersonController {

    private final Logger LOG = LoggerFactory.getLogger(getClass());

    @Autowired
    private final PersonInterface personRepository;

    public PersonController(PersonInterface personRepository) {
        this.personRepository = personRepository;
    }

personRepository cannot be static.

EDIT2: Have also tried this, does not work:

public List<PersonDTO> savePerson(List<PersonDTO> list) {
        list.forEach(dto -> {
            personRepository.save(dto);
        });
        return list;
}
user3672700
  • 152
  • 14
  • Can you please specify what you don't understand in more detail? Your assumption is correct. You can write a map method that will return an object, then finally call subscribe(). For method reference - this should be helpful - https://www.baeldung.com/java-method-references – Most Noble Rabbit Mar 24 '21 at 21:56
  • I've edited the comment with more details. – user3672700 Mar 25 '21 at 20:47

1 Answers1

0

You can write responseToDatabaseEntity method in any class - you can create a processor or a dedicated transformer which is capable of transforming Entity to Data Objects and Vice Versa.

The Map function which is getting called upon a Stream of Response instances will accept reference to any method that takes a single argument of Response instance and returns an object of any type.

So, for example I have created a dedicated transformer

public class EntityDtoTransformer{
    public EntityObject responseToDatabaseEntity(Response response){
        ...
        ...
        return entity;  
    }
}

You can refer this method in Map funnction like:

entityDtoTransformerInstance::responseToDatabaseEntity

Also, you can make this method static and then use it in the map function as

EntityDtoTransformer::responseToDatabaseEntity

If your transformer method is part of the response class your can

.map(res -> response.responseToDatabaseEntity)

or in shorted form

.map(Response::responseToDatabaseEntity)
Amit Phaltankar
  • 3,341
  • 2
  • 20
  • 37
  • I have tried this, the static approach works but I don't want this option, however the first one does not, it simply says `entityDtoTransformerInstance` cannot be resolved. Using my example, I have created this in the `Response` class: `public ResponseDTO responseToDatabaseEntity(Response response){ ResponseDTO a = new ResponseDTO(response); return a; }` and added `.map(responseInstance::responseToDatabaseEntity);` responseInstance cannot be resolved. – user3672700 Mar 25 '21 at 16:25
  • have covered your scenario in the answer – Amit Phaltankar Mar 25 '21 at 19:54
  • Yeah I was able to do something like that but I wrote all the operations inside the .map instead of creating a function. However the problem now, is implementing the `save` method as in the original post I linked, since the : `private final PersonInterface personRepository; public PersonController(PersonInterface personRepository) { this.personRepository = personRepository; }` is in a different class called `PersonController`. I can't use the static approach here because personRepository cannot be static. I'll edit my comment with more details but adapted to Person example. – user3672700 Mar 25 '21 at 20:03
  • Thanks a lot for trying to help, I have edited my comment. – user3672700 Mar 25 '21 at 20:19