Search code examples
javaspringspring-bootspring-webfluxreactive-streams

How to modify or update POJO models at instantiating Java Spring Webflux


i'm working with the Google Maps Geocoding API for Java. I have a basic address POJO. What I want to do is run the createLatCord method on the lat property with the body response of the address, city, state and zipcode

I don't know where I should also modify at, at the model itself, Controller or Service/Repository?

Method I need to run on the lat property at create time

private double createLatCord() throws InterruptedException, ApiException, IOException {
    GeoApiContext context = new 
    GeoApiContext.Builder().apiKey("abc").build();
    GeocodingResult[] results = GeocodingApi.geocode(context, address+city+state+zipcode).await();
//  Gson gson = new GsonBuilder().setPrettyPrinting().create();
    return results[0].geometry.location.lat;
}

Model :


// all the imports ...

public class User {

    private String address;
    private String zipcode;
    private String city;
    private String state;
    private double lat; // <-- Run createLatCord method on this property
    @Id
    private String id;

    public User() {
    }

    public User(String address, String zipcode, String city, String state, double lat) throws InterruptedException, ApiException, IOException {
        this.address = address;
        this.city = city;
        this.state = state;
        this.zipcode = zipcode;
        this.lat = lat;
    }

// GETTERS AND SETTERS HERE FOR THE ABOVE
// Leaving it out cause it's alot

}

Controller:

@PostMapping(path = "", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<User> createUser(@RequestBody Mono<User> user) {
     return userService.createUser(user);
}

Service/ Repository:

@Override
public Mono<User> createUser(Mono<User> userMono) {
   return reactiveMongoOperations.save(userMono);
}

SOLUTION:

Model:

 public Mono<User> createLatCord(User user) throws InterruptedException, ApiException, IOException {
        GeoApiContext context = new GeoApiContext.Builder().apiKey("elnjvw").build();
        GeocodingResult[] results = GeocodingApi.geocode(context, user.getAddress() + user.getCity() + user.getState() + user.getZipcode()).await();
        user.setLat(results[0].geometry.location.lat);
        user.setLng(results[0].geometry.location.lng);
        return Mono.just(user);
    }

Service/ Repository

@Override
    public Mono<User> createUser(Mono<User> userMono) {
        return userMono.flatMap(user -> {
            try {
                return reactiveMongoOperations.save(
                        user.createLatCord(user));
            } catch (InterruptedException | ApiException | IOException e) {
                e.printStackTrace();
            }
            return Mono.just(user);
        });
    }

Solution

  • If I get it right you want to update lat when you save the user. Since your service already receives a Mono you could flatMap it to call the google api and then call the repository. It'll be something like this:

    @Override
    public Mono<User> createUser(Mono<User> userMono) {
        return userMono.flatMap(user -> 
                                methodToCallGoogleApiAndSetValueToUser(user))
                       .subscribe(reactiveMongoOperations::save)
    }
    

    One point is that methodToCallGoogleApiAndSetValueToUser should return a Mono with the updated user.

    Hope this might be helpfull!