Creating a reactive repository

So far, we have been dabbling with Spring Data using our sample domain of employees. We need to shift our focus back to the social media platform that we started building in the previous chapter.

Before we can work on a reactive repository, we need to revisit the Image domain object we defined in the last chapter. Let's adjust it so that it works nicely with MongoDB:

    @Data 
    @Document 
    public class Image { 
 
      @Id final private String id; 
      final private String name; 
    } 

This preceding definition is almost identical to what we saw in the previous chapter, with the following differences:

  • We use @Document to identify this is a MongoDB domain object, but we accept Spring Data MongoDB's decision about what to name the collection (it's the short name of the class, lowercase, that is, image)
  • @Data creates a constructor for all final fields by default, hence, we've marked both id and name as final
  • We have also marked both fields private for proper encapsulation

With that in place, we are ready to declare our social media platform's reactive repository as follows:

    public interface ImageRepository 
     extends ReactiveCrudRepository<Image, String> { 
 
      Mono<Image> findByName(String name); 
    } 

This code for the reactive repository can be described as follows:

  • Our interface extends ReactiveCrudRepository, which, as stated before, comes with a prepackaged set of reactive operations including save, findById, exists, findAll, count, delete, and deleteAll, all supporting Reactor types
  • It includes a custom finder named findByName that matches on Image.name based on parsing the name of the method (not the input argument)

Each of the operations inherited from ReactiveCrudRepository accepts direct arguments or a Reactor-friendly variant. This means, we can invoke either save(Image) or saveAll(Publisher<Image>). Since Mono and Flux both implement Publisher, saveAll() can be used to store either.

ReactiveCrudRepository has ALL of its methods returning either a Mono or a Flux based on the situation. Some, like delete, simply return Mono<Void>, meaning, there is no data to return, but we need the operation's handle in order to issue the Reactive Streams' subscribe call. findById returns a Mono<Image>, because there can be only one. And findAll returns a Flux<Image>.

Before we can get our feet wet in using this reactive repository, we need to preload our MongoDB data store. For such operations, it's recommended to actually use the blocking API. That's because when launching an application, there is a certain risk of a thread lock issue when both the web container as well as our hand-written loader are starting up. Since Spring Boot also creates a MongoOperations object, we can simply grab hold of that, as follows:

    @Component 
    public class InitDatabase { 
      @Bean 
      CommandLineRunner init(MongoOperations operations) { 
        return args -> { 
          operations.dropCollection(Image.class); 
 
          operations.insert(new Image("1", 
           "learning-spring-boot-cover.jpg")); 
          operations.insert(new Image("2", 
           "learning-spring-boot-2nd-edition-cover.jpg")); 
          operations.insert(new Image("3", 
           "bazinga.png")); 
 
          operations.findAll(Image.class).forEach(image -> { 
            System.out.println(image.toString()); 
          }); 
        }; 
      } 
    } 

The preceding code is detailed as follows:

  • @Component ensures that this class will be picked up automatically by Spring Boot, and scanned for bean definitions.
  • @Bean marks the init method as a bean definition requiring a MongoOperations. In turn, it returns a Spring Boot CommandLineRunner, of which all are run after the application context is fully formed (though in no particular order).
  • When invoked, the command-line runner will use MongoOperations, and request that all entries be deleted (dropCollection). Then it will insert three new Image records. Finally, it will fetch with (findAll) and iterate over them, printing each out.

With sample data loaded, let's hook things into our reactive ImageService in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.9.124